Lambda expressions for Java

Introduction to Lambda
Lambda expression is a new feature of JDK8. It can replace most anonymous internal classes and write more elegant Java code. Especially in collection traversal and other collection operations, it can greatly optimize the code structure.

JDK also provides a large number of built-in functional interfaces for us to use, making the use of Lambda expressions more convenient and efficient.

Requirements for interfaces
Although some interfaces can be simply implemented using lambda expressions, not all interfaces can be implemented using lambda expressions. Lambda stipulates that there can only be one method to be implemented in the interface, not only one method in the interface

jdk 8 has another new feature: default. The method modified by default will have a default implementation, which is not a method that must be implemented, so it does not affect the use of Lambda expressions.

@FunctionalInterface
Modifying a functional interface requires only one abstract method in the interface. This annotation often appears with lambda expressions.

Lambda basic grammar
We give six interfaces here, and all operations in the following text are described by using these six interfaces.

/**Multi parameter no return*/
@FunctionalInterface
public interface NoReturnMultiParam {
    void method(int a, int b);
}

/**No parameter, no return value*/
@FunctionalInterface
public interface NoReturnNoParam {
    void method();
}

/**A parameter is not returned*/
@FunctionalInterface
public interface NoReturnOneParam {
    void method(int a);
}

/**Multiple parameters have return values*/
@FunctionalInterface
public interface ReturnMultiParam {
    int method(int a, int b);
}

/*** Return without parameters*/
@FunctionalInterface
public interface ReturnNoParam {
    int method();
}

/**A parameter has a return value*/
@FunctionalInterface
public interface ReturnOneParam {
    int method(int a);
}

The syntax form is () - > {}, where () is used to describe the parameter list, {} is used to describe the method body, and > is the lambda operator, which is read as (goes to).

import lambda.interfaces.*;

public class Test1 {
    public static void main(String[] args) {

        //No parameters, no return
        NoReturnNoParam noReturnNoParam = () -> {
            System.out.println("NoReturnNoParam");
        };
        noReturnNoParam.method();

        //A parameter is not returned
        NoReturnOneParam noReturnOneParam = (int a) -> {
            System.out.println("NoReturnOneParam param:" + a);
        };
        noReturnOneParam.method(6);

        //Multiple parameters are not returned
        NoReturnMultiParam noReturnMultiParam = (int a, int b) -> {
            System.out.println("NoReturnMultiParam param:" + "{" + a +"," + + b +"}");
        };
        noReturnMultiParam.method(6, 8);

        //No parameter has a return value
        ReturnNoParam returnNoParam = () -> {
            System.out.print("ReturnNoParam");
            return 1;
        };

        int res = returnNoParam.method();
        System.out.println("return:" + res);

        //A parameter has a return value
        ReturnOneParam returnOneParam = (int a) -> {
            System.out.println("ReturnOneParam param:" + a);
            return 1;
        };

        int res2 = returnOneParam.method(6);
        System.out.println("return:" + res2);

        //Multiple parameters have return values
        ReturnMultiParam returnMultiParam = (int a, int b) -> {
            System.out.println("ReturnMultiParam param:" + "{" + a + "," + b +"}");
            return 1;
        };

        int res3 = returnMultiParam.method(6, 8);
        System.out.println("return:" + res3);
    }
}

Lambda syntax simplification
We can further simplify the code and write more elegant code by observing the following code.

Copy
import lambda.interfaces.*;

public class Test2 {
    public static void main(String[] args) {

        //1. Simplify parameter types. You can not write parameter types, but you must not write all parameters
        NoReturnMultiParam lamdba1 = (a, b) -> {
            System.out.println("Simplified parameter type");
        };
        lamdba1.method(1, 2);

        //2. Simplify parameter parentheses. If there is only one parameter, parameter parentheses can be omitted
        NoReturnOneParam lambda2 = a -> {
            System.out.println("Simplified parameter parentheses");
        };
        lambda2.method(1);

        //3. Simplify the method body braces. If the method bar has only one statement, you can win the method body braces
        NoReturnNoParam lambda3 = () -> System.out.println("Simplified method body braces");
        lambda3.method();

        //4. If the method body has only one statement and is a return statement, the method body braces can be omitted
        ReturnOneParam lambda4 = a -> a+3;
        System.out.println(lambda4.method(5));

        ReturnMultiParam lambda5 = (a, b) -> a+b;
        System.out.println(lambda5.method(1, 1));
    }
}

Common examples of Lambda expressions

1.lambda expression reference method
Sometimes we don't have to rewrite the method of an anonymous inner class ourselves. We can use the interface of lambda expression to quickly point to an implemented method.

grammar

Method owner: method name. The owner of static method is the class name, and the owner of common method is the object

public class Exe1 {
    public static void main(String[] args) {
        ReturnOneParam lambda1 = a -> doubleNum(a);
        System.out.println(lambda1.method(3));

        //lambda2 refers to the already implemented doubleNum method
        ReturnOneParam lambda2 = Exe1::doubleNum;
        System.out.println(lambda2.method(3));

        Exe1 exe = new Exe1();

        //lambda4 refers to the already implemented addTwo method
        ReturnOneParam lambda4 = exe::addTwo;
        System.out.println(lambda4.method(2));
    }

    /**
     * requirement
     * 1.The number and type of parameters shall be consistent with those defined in the interface
     * 2.The return value type should be consistent with that defined in the interface
     */
    public static int doubleNum(int a) {
        return a * 2;
    }

    public int addTwo(int a) {
        return a + 2;
    }
}

2. Reference of construction method
In general, we need to declare the interface, which is an object generator, instantiate the object by way of class name: new, and then call the method to return the object.

interface ItemCreatorBlankConstruct {
    Item getItem();
}
interface ItemCreatorParamContruct {
    Item getItem(int id, String name, double price);
}

public class Exe2 {
    public static void main(String[] args) {
        ItemCreatorBlankConstruct creator = () -> new Item();
        Item item = creator.getItem();

        ItemCreatorBlankConstruct creator2 = Item::new;
        Item item2 = creator2.getItem();

        ItemCreatorParamContruct creator3 = Item::new;
        Item item3 = creator3.getItem(112, "mouse", 135.99);
    }
}

3.lambda expression creation thread
In the past, we used to create a Thread object, and then override the run() method through an anonymous inner class. When we mention an anonymous inner class, we should think of using lambda expressions to simplify the Thread creation process.

  Thread t = new Thread(() -> {
      for (int i = 0; i < 10; i++) {
        System.out.println(2 + ":" + i);
      }
    });
  	t.start();

4. Traverse the set
We can call the public void foreach (Consumer <? Super E > action) method of the collection to traverse the elements in the collection through lambda expressions. The following are the methods of the Consumer interface and the operations of traversing the collection. The Consumer interface is a functional interface provided by jdk.

 @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
        //....
    }
   ArrayList<Integer> list = new ArrayList<>();

      Collections.addAll(list, 1,2,3,4,5);

      //lambda expression method reference
      list.forEach(System.out::println);

      list.forEach(element -> {
        if (element % 2 == 0) {
          System.out.println(element);
        }
      });

5. Delete an element in the collection
We use the public Boolean removeif (predict <? Super E > filter) method to delete an element in the collection. Predict is also a functional interface provided by jdk, which can simplify the programming.

  ArrayList<Item> items = new ArrayList<>();
      items.add(new Item(11, "Small toothbrush", 12.05 ));
      items.add(new Item(5, "Japanese toilet cover", 999.05 ));
      items.add(new Item(7, "Gree air conditioner", 888.88 ));
      items.add(new Item(17, "soap", 2.00 ));
      items.add(new Item(9, "Refrigerator", 4200.00 ));

      items.removeIf(ele -> ele.getId() == 7);

      //Traverse through foreach to see if it has been deleted
      items.forEach(System.out::println);

6. Sorting of elements in the set
In the past, if we wanted to sort the elements in the collection, we had to call the sort method and pass in the comparator anonymous inner class to override the compare method. Now we can use lambda expressions to simplify the code.

   ArrayList<Item> list = new ArrayList<>();
        list.add(new Item(13, "vest", 7.80));
        list.add(new Item(11, "Half sleeve", 37.80));
        list.add(new Item(14, "Windbreaker", 139.80));
        list.add(new Item(12, "Autumn pants", 55.33));

        /*
        list.sort(new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return o1.getId()  - o2.getId();
            }
        });
        */

        list.sort((o1, o2) -> o1.getId() - o2.getId());

        System.out.println(list);

Closure problems in Lambda expressions

This problem also exists in anonymous inner classes. If we release the annotation, we will report an error and tell me that the num value is final and cannot be changed. Although we did not identify the num type as final here, the virtual opportunity helped us add the final modifier keyword during compilation.

import java.util.function.Consumer;
public class Main {
    public static void main(String[] args) {

        int num = 10;

        Consumer<String> consumer = ele -> {
            System.out.println(num);
        };

        //num = num + 2;
        consumer.accept("hello");
    }
}

Some common functional interfaces

Tags: Java Lambda

Posted on Tue, 30 Nov 2021 10:34:20 -0500 by mickeyunderscore