Lambda表达式的使用

Lambda表达式的使用


1. Lambda表达式的语法


Lambda表达式本质就是一个匿名函数,在函数的语法中包含返回值类型、方法名、形参列表和方法体等,而在Lambda表达式中我们只需要关心形参列表方法体即可。
在Java语言中,Lambda表达式的语法为“(形参列表) -> {方法体}”,其中“->”为 lambda操作符或箭头操作符,“形参列表”为对应接口实现类中重写方法的形参列表,“方法体”为对应接口实现类中重写方法的方法体。

[!tip]

因为函数接口中只有一个方法,所以方法名和返回值类型可以省略。

以匿名内部类为例,从而将匿名内部类演化为Lambda表达式

  • 匿名类
1
2
3
4
5
6
7
8
List<Integer> list = Arrays.asList(3, 6, 1, 7, 2, 5, 4);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println("排序后:" + list);
  • Lambda表达式
1
2
3
4
5
List<Integer> list = Arrays.asList(3, 6, 1, 7, 2, 5, 4);
Collections.sort(list, (Integer o1, Integer o2) -> {
return o2 - o1;
});
System.out.println("排序后:" + list);

我们只需将匿名内部类中的方法参数列表和方法体保存即可。

2. Lambda表达式的基本使用


2.1 无返回值函数式接口

2.1.1 无返回值无参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface NoParameterNoReturn {
void test();
}

public class Test01 {
public static void main(String[] args) {
// 方式一:使用匿名内部类来实现
NoParameterNoReturn obj1 = new NoParameterNoReturn() {
@Override
public void test() {
System.out.println("无参无返回值");
}
};
obj1.test();

// 方式二:使用Lambda表达式来实现
NoParameterNoReturn obj2 = () -> {
System.out.println("无参无返回值");
};
obj2.test();
}
}

思路:提取参数列表和函数方法体。

2.1.2 无返回值一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface OneParameterNoReturn {
void test(int num);
}

public class Test01 {
public static void main(String[] args) {
// 方式一:使用匿名内部类来实现
OneParameterNoReturn obj1 = new OneParameterNoReturn() {
@Override
public void test(int num) {
System.out.println("无返回值一个参数 --> " + num);
}
};
obj1.test(10);

// 方式二:使用Lambda表达式来实现
OneParameterNoReturn obj2 = (int num) -> {
System.out.println("无返回值一个参数 --> " + num);
};
obj2.test(20);
}
}

2.1.3 无返回值多个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface MoreParameterNoReturn {
void test(String str1, String str2);
}
public class Test01 {
public static void main(String[] args) {
// 方式一:使用匿名内部类来实现
MoreParameterNoReturn obj1 = new MoreParameterNoReturn() {
@Override
public void test(String str1, String str2) {
System.out.println(str1 + " : " + str2);
}
};
obj1.test("hello", "world");

// 方式二:使用Lambda表达式来实现
MoreParameterNoReturn obj2 = (String str1, String str2) -> {
System.out.println(str1 + " : " + str2);
};
obj2.test("你好", "世界");
}
}

2.2 有返回值函数接口

2.2.1 有返回值无参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface NoParameterHasReturn {
int test();
}

public class Test01 {
public static void main(String[] args) {
// 方式一:使用匿名内部类来实现
NoParameterHasReturn obj1 = new NoParameterHasReturn() {
@Override
public int test() {
return 520;
}
};
System.out.println(obj1.test()); // 输出:520

// 方式二:使用Lambda表达式来实现
NoParameterHasReturn obj2 = () -> {
return 1314;
};
System.out.println(obj2.test()); // 输出:1314
}
}

2.2.2 有返回值一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 情况二:有返回值一个参数
interface OneParameterHasReturn {
String test(double num);
}

public class Test01 {
public static void main(String[] args) {
// 方式一:使用匿名内部类来实现
OneParameterHasReturn obj1 = new OneParameterHasReturn() {
@Override
public String test(double num) {
return "传入的小数为:" + num;
}
};
System.out.println(obj1.test(520.0));

// 方式二:使用Lambda表达式来实现
OneParameterHasReturn obj2 = (double num) -> {
return "传入的小数为:" + num;
};
System.out.println(obj2.test(1314.0));
}
}

2.2.3 有返回值多个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface MoreParameterHasReturn {
String test(int num1, int num2);
}
public class Test01 {
public static void main(String[] args) {
// 方式一:使用匿名内部类来实现
MoreParameterHasReturn obj1 = new MoreParameterHasReturn() {
@Override
public String test(int num1, int num2) {
return "运算的结果为:" + (num1 + num2);
}
};
System.out.println(obj1.test(10, 20));

// 方式二:使用Lambda表达式来实现
MoreParameterHasReturn obj2 = (int num1, int num2) -> {
return "运算的结果为:" + (num1 + num2);
};
System.out.println(obj2.test(20, 30));
}
}

3. Lambda表达式的语法精简


在以上代码中,虽然Lambda表达式的语法已经很简洁了,但是Lambda表达式的语法格式还可以更加的精简,从而写出更加优雅的代码,但是相应的代码可读性也会变差。在以下的应用场景中,我们就可以对Lambda表达式的语法进行精简,场景如下:

  1. 形参类型可以省略,如果需要省略,则每个形参的类型都要省略。
  2. 如果形参列表中只存在一个形参,那么形参类型和小括号都可以省略。
  3. 如果方法体当中只有一行语句,那么方法体的大括号也可以省略。
  4. 如果方法体中只有一条return语句,那么大括号可以省略,且必须去掉return关键字。
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class LambdaTest {
public static void main(String[] args) {
// (1)形参类型可以省略,如果需要省略,每个形参的类型都要省略。
// 没有精简的Lambda表达式代码
MoreParameterNoReturn obj1 = (String str1, String str2) -> {
System.out.println(str1 + " : " + str2);
};
obj1.test("hello", "world");
// 精简之后的Lambda表达式代码
MoreParameterNoReturn obj2 = (str1, str2) -> {
System.out.println(str1 + " : " + str2);
};
obj2.test("你好", "世界");

// (2)如果形参列表中只有一个形参,那么形参类型和小括号都可以省略。
// 没有精简的Lambda表达式代码
OneParameterHasReturn obj3 = (double num) -> {
return "传入的小数为:" + num;
};
System.out.println(obj3.test(520.0));
// 精简之后的Lambda表达式代码
OneParameterHasReturn obj4 = num -> {
return "传入的小数为:" + num;
};
System.out.println(obj4.test(1314.0));

// (3)如果方法体当中只有一行代码,那么方法体的大括号也可以省略。
// 没有精简的Lambda表达式代码
NoParameterNoReturn obj5 = () -> {
System.out.println("无参无返回值");
};
obj5.test();
// 精简之后的Lambda表达式代码
NoParameterNoReturn obj6 = () -> System.out.println("无参无返回值");
obj6.test();

// (4)方法体中只有一条return语句,则大括号可以省略,且必须去掉return关键字
// 没有精简的Lambda表达式代码
MoreParameterHasReturn obj7 = (int a, int b) -> {
return "运算的结果为:" + (a + b);
};
System.out.println(obj7.test(10, 20));
// 精简之后的Lambda表达式代码
MoreParameterHasReturn obj8 = (a, b) -> "运算的结果为:" + (a + b);
System.out.println(obj8.test(20, 30));
}
}

4. 四个基本的函数式接口


名字 接口名 对应的抽象方法
消费 Consumer void accept(T t);
生产 Supplier T get();
转换 Function<T, R> R apply(T t);
判断 Predicate boolean test(T t);

以上的函数式接口都在java.util.function包中,通常函数接口出现的地方都可以使用Lambda表达式。