Data Structure Java Data Structure --- Lambda Expression

Lambda expressions

1. Background of Lambda Expressions

Lambda expressions are an important new feature in JDK 1.8.
Lambda expressions allow you to replace functional interfaces with expressions. A lambda expression is just like a method, it provides a normal parameter list and a body (body, which can be an expression or a code block) that uses those parameters.
A Lambda expression can be regarded as an anonymous function , named after the lambda calculus in mathematics, and can also be called a Closure.

1.1 Syntax of Lambda Expressions

Basic syntax:(parameters)->expression 或 (parameters)->{statements;}

Lambda expressions consist of three parts :

  1. paramaters: Similar to the formal parameter list in the method, the parameters here are the parameters in the functional interface. The parameter types here can be explicitly declared or not declared and implicitly inferred by the JVM. Also, parentheses can be omitted when there is only one inferred type.
  2. ->: can be understood as the meaning of "to be used for"
  3. Method body: It can be an expression or a code block, which is the implementation of the method in the functional interface. A block of code can return a value or nothing, where a block of code is equivalent to the method body of a method. If it is an expression, it can also return a value or nothing.
// 1. 不需要参数,返回值为 2
    () -> 2;
// 2. 接收一个参数(数字类型),返回其2倍的值
    x -> 2 * x;
// 3. 接受2个参数(数字),并返回他们的和
    (x, y) -> x + y;
// 4. 接收2个int型整数,返回他们的乘积
    (int x, int y) -> x * y;
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
    (String s)->System.out.print(s);

1.2 Functional interface

Functional interface definition: An interface has one and only one abstract method.

Notice:

  1. An interface is a functional interface if it has only one abstract method
  2. If we declare the @FunctionalInterface annotation on an interface, the compiler will require the interface according to the definition of the functional interface, so if there are two abstract methods, the program compilation will report an error. So, in a sense, as long as you guarantee that there is only one abstract method in your interface, you can leave this annotation alone. Plus it will be automatically detected.

Defined by:

@FunctionalInterface
interface NoParameterNoReturn {
    
    
    void test(); // 只能有一个抽象方法
}

another way:

@FunctionalInterface
interface NoParameterNoReturn {
    
    
    void test(); // 只能有一个抽象方法
    default void test2(){
    
    
        System.out.println("111");
    }
}

insert image description here

2. Basic use of lambda expressions

2.1 No return value and no parameters

//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
    
    
    void test();
}
public class Test {
    
    
 public static void main2(String[] args) {
    
    
        //无返回值无参数
        NoParameterNoReturn parameterNoReturn = ()-> System.out.println("重写方法");
    }
}

2.2 One parameter with no return value

// 无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
    
    
    void test(int a);
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        //无返回值有一个参数
        OneParameterNoReturn oneParameterNoReturn = (a)->{
    
    System.out.println(a);};
        oneParameterNoReturn.test(10);

        OneParameterNoReturn oneParameterNoReturn1 = a-> System.out.println(a);
        oneParameterNoReturn1.test(10);

        OneParameterNoReturn oneParameterNoReturn2 = System.out::println;
        oneParameterNoReturn2.test(10);
    }
}

2.3 Multiple parameters without return value

//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
    
    
    void test(int a,int b);
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        MoreParameterNoReturn moreParameterNoReturn = (a,b)->{
    
    
            System.out.println(a+b);
        };
        moreParameterNoReturn.test(10,20);
        
        MoreParameterNoReturn moreParameterNoReturn1 = (a, b) -> System.out.println(a+b);
        moreParameterNoReturn1.test(20,30);
    }
}

2.4 With return value and no parameters

//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
    
    
    int test();
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        NoParameterReturn noParameterReturn = ()->{
    
    return 10;};
        int ret = noParameterReturn.test();
        System.out.println(ret);

        NoParameterReturn noParameterReturn1 = ()->10;
        int ret1 = noParameterReturn1.test();
        System.out.println(ret1);
    }
}

2.5 One parameter with return value

//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
    
    
    int test(int a);
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        OneParameterReturn oneParameterReturn = (a) -> {
    
    return a+11;};
        int ret = oneParameterReturn.test(10);
        System.out.println(ret);
        
        OneParameterReturn oneParameterReturn1 = a -> a+11;
        System.out.println(oneParameterReturn1.test(10));
    }
}

2.6 Multiple parameters with return value

//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
    
    
    int test(int a,int b);
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        MoreParameterReturn moreParameterReturn = (a,b) -> {
    
    return a+b;};
        moreParameterReturn.test(10,20);
        
        MoreParameterReturn moreParameterReturn1 = (a,b) -> a+b;
        System.out.println(moreParameterReturn1.test(30,40));
    }
}

2.7 PriorityQueue usage example

insert image description here

2.8 Syntax simplification

  1. The parameter type can be omitted, and if it needs to be omitted, the type of each parameter must be omitted.
  2. There is only one parameter in the parentheses of the parameter, then the parentheses can be omitted
  3. If there is only one line of code in the method body, the curly braces can be omitted
  4. If there is only one statement in the method body, which is a return statement, the curly braces can be omitted and the return keyword is removed.

3. Variable capture

There is variable capture in lambda expressions. After understanding variable capture, we can better understand the scope of lambda expressions. In anonymous classes in Java, there will be variable capture.

3.1 Variable capture of anonymous inner classes

class Test1{
    
    
    public void func(){
    
    
        System.out.println("func");
    }
}
public class TestDemo {
    
    
    public static void main(String[] args) {
    
    
        int a = 100;
        new Test1(){
    
    
            @Override
            public void func() {
    
    
                System.out.println("内部类,重写了func方法");
                System.out.println("捕获变量, 要么是常量,要么未发生的变量" + a);
            }
        }.func();
    }
}

insert image description here
The variable a in the above code is the captured variable. This variable is either modified by final, if it is not modified by final, you must ensure that it is not modified before use.

Bad example 1:
insert image description here
Bad example 2:
insert image description here

3.2 Lambda's variable capture

@FunctionalInterface
interface NoParameterNoReturn {
    
    
	void test();
}
public static void main(String[] args) {
    
    
	int a = 10;
	NoParameterNoReturn noParameterNoReturn = ()->{
    
    
		// a = 99; error
		System.out.println("捕获变量:"+a);
	};
	noParameterNoReturn.test();
}

4. The use of Lambda in collections

In order to make Lambda and Java's collection class set better together, some new interfaces have been added to the collection for docking with Lambda expressions.

corresponding interface Added method
Collection removeIf() spliterator() stream() parallelStream() forEach()
List replaceAll() sort()
Map getOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()

4.1 Collection interface

forEach()Method demonstration
Example of use:

class Test1{
    
    
    public void func(){
    
    
        System.out.println("func");
    }
}
public class TestDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list = new ArrayList<>();
        list.add("ze");
        list.add("www");
        list.add("qwer");
        list.add("lambda");

        list.forEach(new Consumer<String>() {
    
    
            @Override
            public void accept(String s) {
    
    
                System.out.println(s);
            }
        });

        list.forEach(s-> System.out.println(s));
    }
}

insert image description here

4.2 List interface

sort()Demonstration of the method
Example of use:

public static void main(String[] args) {
    
    
        ArrayList<String> list = new ArrayList<>();
        list.add("ze");
        list.add("www");
        list.add("qwer");
        list.add("lambda");

        list.sort(new Comparator<String>() {
    
    
            @Override
            public int compare(String o1, String o2) {
    
    
                return o1.length()-o2.length();
            }
        });
        System.out.println(list);

        list.sort((o1, o2) -> o1.length()-o2.length());
        System.out.println(list);
}

insert image description here

4.3 Map interface

forEach()Method
code example:

    public static void main(String[] args) {
    
    
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"ze");
        map.put(2,"www");
        map.put(3,"qwer");
        map.put(4,"lambda");

        map.forEach(new BiConsumer<Integer, String>() {
    
    
            @Override
            public void accept(Integer integer, String s) {
    
    
                System.out.println("key:"+integer+"value:"+s);
            }
        });

        map.forEach((key,value)-> System.out.println("key:"+key+"value:"+value));
    }

insert image description here

5. Summary

The advantages of lambda expressions are obvious. At the code level, the code becomes very concise. The disadvantage is also obvious, the code is not easy to read.

advantage:

  1. Simple code, rapid development
  2. Convenient functional programming
  3. very easy to parallelize
  4. Java introduces Lambda to improve collection operations

shortcoming:

  1. Poor code readability
  2. In non-parallel computing, many computations may not have higher performance than traditional for
  3. Not easy to debug

Guess you like

Origin blog.csdn.net/wwzzzzzzzzzzzzz/article/details/123261497