Detailed explanation of Lambda expressions (new features of java8, functional programming)

An important new feature was introduced in JDK1.8: Lambda expressions.

Lambda allows functions to be used as parameters of a method (functions are passed into the method as parameters).

Using Lambda expressions can make the code more concise and compact. Before learning Lambda expressions, let's first think about why it appears.

1. Why does Lambda expression appear?

First, let's think about how to represent a value in java? Very simple, define a variable, and then assign
Insert picture description here

So how to express the execution logic of a code block? It is also very simple, define a function, and write the corresponding execution logic on the function method body
Insert picture description here

But what if I want to assign this function to a variable (aBlockOfCode) and pass it as an input parameter?

For example:

Insert picture description here

Before Java 8, this was illegal. But after the advent of Java 8, using Lambda features, it can be done, and the designer of Lambda has also kindly helped us simplify this definition:

Insert picture description here

As you can see, we have assigned "a piece of code" to a variable very elegantly. And "this piece of code", or "this function assigned to a variable", is a Lambda expression .

And what is the type of this variable?

In Java8, a new interface type is defined: functional interface, an interface type that an interface function needs to be implemented, we call it "functional interface" , and an exclusive declaration @FunctionalInterface is also defined for this interface , in the interface Adding the statement above means that only one function in the interface needs to be implemented

Insert picture description here

In fact, we found that the above expression actually achieves the same purpose by defining an implementation class of an excuse and then instantiating it, but the amount of code is much larger.

Insert picture description here

This is also the most intuitive function of Lambda expressions: it makes the code extremely concise.

And Lambda combines many new features of Java8: FunctionalInterface Lib, forEach, stream(), method reference, etc. You will see that this advantage will be infinitely magnified!

2. The basic syntax of Lambda expressions

The two grammatical formats of Lambda expressions are as follows:

  1. (parameters) -> expression
  2. (parameters) -> {statements;}

The following are the important characteristics of lambda expressions:

1. Optional type declaration : there is no need to declare the parameter type, the compiler can uniformly identify the parameter value.

2. Optional parameter parentheses : one parameter does not need to define parentheses, but 0 or more parameters need to define parentheses.

3. Optional curly braces: If the expression has only one line, the curly braces on both sides of the expression can be omitted.

4. Optional return keyword : If the subject has only one expression return value, the compiler will automatically return the value. The braces need to specify that the expression returns a value.

Simple example of lambda expression

  • 1. Multi-parameter case

    (1). The basic format of lambda expression is (x1,x2)->{Expression...};

    (2). In the above formula, the lambda expression has two parameters. In this case, the parameter type can be omitted, but the parentheses on both sides cannot be omitted.

    (3)...If the expression has only one line, the curly braces on both sides of the expression can be omitted

    //接受2个带参参数,并返回他们的差值 
    (int x, String y) -> String.valueOf(x) + y  
    
    // 4. 接收2无参参数,返回他们的和  
    (x, y) -> x – y  
    
    
  • 2. The case without parameters

    The parentheses of the parameters cannot be omitted, other syntax is the same as multiple parameters

//创建并启动一个线程
new Thread(()-> System.out.println("hello, i am thread!")).start();
  • 3. The case of one parameter

    You can omit the parentheses and types of the parameters, other syntax is the same as multiple parameters

//  接收一个参数,可以省略参数的括号和类型
x -> 2 * x  
 
// 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

3. Commonly used functional interfaces provided in Java 8

As we said earlier, in order to cooperate with the use of Lambda expressions, a new interface type is defined in Java 8: Functional interface, that is, an interface type that an interface function needs to be implemented , which is declared by @FunctionalInterface . In fact, in order to facilitate our use, Java also provides a lot of commonly used functional interfaces.

Use functional interface package: java.util.function

Insert picture description here

Common ones are
1. Consumer interface Consumer : void accept(T t): Receive a parameter for consumption, but does not need to return a result.

2. Supply interface Supplier : T get(): returns a custom data

3. Functional interface Function<T,R> : R apply(T t): Pass in a parameter and return the desired result.

4. Assertion interface Predicate : boolean test(T t): Pass in a parameter and return a boolean value

5. Other similar interfaces :
UnaryOperator: unary operator, a subclass of Function, but the input parameters and return results of this interface must be of the same type.

BiFunction<T, U, R>: A bit more advanced than Function, it can receive two parameters and still return a result after application.

BiConsumer<T,U>: It is also a bit more advanced than Consumer, and can receive two parameters for consumption without returning the result.

BiPredicate<T,U>: It is also a bit more advanced than Predicate. It can receive two parameters and return a bool value after judgment.

For example:
Insert picture description here

4. Method reference

Java 8 also added a new keyword "::" We can use the "::" keyword to access class construction methods, object methods, and static methods .

The demonstration is as follows:

1. First customize a class

class Demo {
    
    
    //无参构造
    Demo() {
    
    }
    //有参构造
    Demo(String something) {
    
    
        System.out.println(something);
    }
    //多参构造
    Demo(String something,Integer num) {
    
    
        System.out.println(something+num);
    }

    //静态方法
    static String startsMethod(String s) {
    
    
        return String.valueOf(s.charAt(0));
    }

    //
    String methodOne(String s) {
    
    
        return String.valueOf(s.charAt(s.length()-1));
    }

    void methodTwo() {
    
    
        System.out.println();
    }
}

2. First define a functional interface

[External link image transfer failed. The origin site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-tEDdjg5i-1606478057603) (Detailed explanation of Lambda expression, new feature of java8.assets/1606463685803.png)]

Interface IConvert, the passed parameter is type F, and the return type is T.

Next, let us demonstrate the method access through the :: keyword.

  1. Access static method

     IConvert<String,String> ic1 =  Demo::startsMethod;
    ic1.convert("静态方法访问");
    
  2. Access object method

     IConvert<String,String> ic2 =  new Demo()::methodOne;
     ic2.convert("对象方法访问");
    
  3. Access constructor

    IConvert<String,Demo> ic3 =  Demo::new;
    ic3.convert("构造方法访问");
    

We can think of it this way, taking the interface IConvert<F,T> as a well-defined template, and each method in the Demo class as the implementation of this template. As long as the method in the Demo conforms to the definition of input and output parameters of the IConvert interface, you can directly Assign the method to the template.

Quoted in reference:
https://www.zhihu.com/question/20125256/answer/324121308

Guess you like

Origin blog.csdn.net/weixin_43828467/article/details/110244897