Introduction to Lambda expressions, read this article is enough!

Introduction to Lambda

Lambda expression is a new feature of JDK8. It can replace most anonymous inner 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 implemented simply by using lambda expressions, not all interfaces can be implemented by 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). Focus on Java Architect Technology

import lambda.interfaces.*;

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

        //No parameter, 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 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.

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 brace");
        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

lambda expression reference method

Sometimes we don't have to rewrite the method of an anonymous inner class by 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 ordinary 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;
    }
}

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);
    }
}

lambda expression creation thread

In the past, we used to create Thread objects, and then override the run() method through anonymous inner classes. When we mention anonymous inner classes, we should think of using lambda expressions to simplify the process of Thread creation.

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

Traversal 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);
        }
      });


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);

      //Through foreach traversal, check whether it has been deleted
      items.forEach(System.out::println);

Sorted elements within a collection

In the past, if we wanted to sort the elements in the collection, we had to call the sort method and pass in the anonymous inner class of the comparator 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 trousers", 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 problem in Lambda expression

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");
    }
}

Added by aconway on Thu, 17 Feb 2022 10:36:38 +0200