Mybatis-plus进阶篇(三)

[toc]

1.1 Lambda表达式的语法

基本语法:

(parameters) -> expression 或 (parameters) ->{ statements; }

Lambda表达式由三部分组成:

  1. paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
  2. ->:可理解为“被用于”的意思
  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

最经典的比如java中的forEach方法:

1
2
3
4
5
6
7
8
9
10
import java.util.Arrays;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List<String> list = Arrays.asList('潘', '家', '辉', '别', '雪', '了');

// Lambda表达式作为参数传递给forEach方法
list.forEach(list -> System.out.print(list+" "));
}
}

1.2 函数式接口

要了解 Lambda 表达式 , 首先需要了解什么是函数式接口,

函数式接口定义:

一个接口有且只有一个抽象方法 。

注意:

  1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
  2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     

    // 定义一个函数式接口
    @FunctionalInterface
    interface Task {
    //注意只能有一个方法
    void perform();
    }

    public class LambdaExample {
    public static void main(String[] args) {
    // 创建一个助手对象,使用Lambda表达式实现任务
    Task assistant = () -> System.out.println("助手正在切洋葱...");

    // 调用厨师的方法,传递助手对象执行任务
    cookMeal(assistant);
    }

    public static void cookMeal(Task task) {
    // 准备食材
    System.out.println("准备食材...");

    // 执行任务
    task.perform();

    // 煮菜
    System.out.println("开始烹饪...");
    }
    }
    如果在接口再定义一个方法,则会报错。

1.3 方法引用

先来看一下什么是方法引用:

方法引用其实是Lambda表达式的另一种写法,当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用;
注意: 实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符::将方法名和对象或类的名字分隔开来,三种主要使用情况为

对象::实例方法
类::静态方法
类::实例方法

对象::实例方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.function.Consumer;

public class MyTest {
public static void main(String[] args) {
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("aaaaaaaaaaaaaa");
//aaaaaaaaaaaaaa

//简写1:
Consumer<String> consumer1 = (String s) -> {
System.out.println(s);
};
consumer1.accept("abc");
//abc

//简写2:
Consumer<String> consumer2 = (s) -> System.out.println(s);
consumer2.accept("bcd");
//bcd

//简写3:
Consumer<String> consumer3 = System.out::println;
consumer3.accept("abc");
//abc
}
}

类::静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.function.BinaryOperator;

public class MyTest1 {
public static void main(String[] args) {
BinaryOperator<Double> operator = new BinaryOperator<Double>(){
@Override
public Double apply(Double o, Double o2) {
return Math.max(o,o2);
}
};

System.out.println(operator.apply(2.13, 3.12));//3.12

BinaryOperator<Double> operator2 = (o, o2) -> Math.max(o,o2);
System.out.println(operator2.apply(2.13, 3.12));//3.12

BinaryOperator<Double> operator3 = Math::max;

Double max = operator3.apply(5.0, 20.0);
System.out.println(max);//20.0

}
}

类::实例方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.Comparator;
public class MyTest2 {
public static void main(String[] args) {
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};

System.out.println(comparator.compare("20", "12"));//1

Comparator<String> comparator1 = String::compareTo;
System.out.println(comparator1.compare("20", "12"));//1
}
}

1.4 构造引用

格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.function.Supplier;

public class Mytest {
public static void main(String[] args) {
Supplier<Student> supplier = new Supplier<Student>() {
@Override
public Student get() {
return new Student();
}
};

Student student = supplier.get();

Supplier<Student> supplier1 = () -> new Student();
Student student1 = supplier1.get();
}
}