L
L
LearnJava
Search…
Java的Lambda表达式

1. 什么是Lambda表达式

简单的说,Lambda表达式就是匿名方法。Lambda表达式让程序员能够使用更加简洁的代码,但是同样也使代码的可读性比较差。
Lambda表达式也叫做匿名方法或者闭包。

2. 和匿名内部类做对比

Lambda是匿名方法,这个时候我们会想想到匿名内部类,我们来回想一下匿名内部类的用法,比如下面的代码就是使用匿名内部类实现了一个线程。
1
public class Test {
2
public static void main(String[] args) {
3
Thread t = new Thread(new Runnable() {
4
@Override
5
public void run() {
6
System.out.println("线程:" + Thread.currentThread().getName());
7
}
8
});
9
t.start();
10
}
11
}
Copied!
我们一般的做法是写一个Runnable接口的实现类,然后new一个实现类再传给Thread的构造器。如下:
1
public class Test {
2
3
public static void main(String[] args) {
4
MyThread myThread = new MyThread();
5
Thread t = new Thread(myThread);
6
t.start();
7
}
8
9
static class MyThread implements Runnable {
10
@Override
11
public void run() {
12
System.out.println("线程:" + Thread.currentThread().getName());
13
}
14
}
15
16
}
Copied!
可以看到使用匿名内部类的话就省略了新建Runnable接口的实现类这一步骤。

3. 使用Lambda表达式

上面使用匿名内部类的写法,如果使用Lambda表达式可以写成下面这样:
1
public class Test {
2
public static void main(String[] args) {
3
Thread t = new Thread(() -> {
4
System.out.println("线程:" + Thread.currentThread().getName());
5
});
6
t.start();
7
}
8
}
Copied!
这样有一个问题,如果接口里面有多个方法,那么Lambda表达式怎么知道实现的是哪个方法呢?我们通过代码测试一下:
1
package com.wangjun.othersOfJava;
2
3
public class LambdaTest {
4
5
public static void main(String[] args) {
6
Animal a = () -> { // 编译报错:The target type of this expression must be a functional interface
7
System.out.println("狗狗吃饭");
8
};
9
a.eat();
10
}
11
interface Animal {
12
public void eat();
13
public void duty();
14
}
15
}
Copied!
可以看到编译报错,这个提到一个functional interface,就是函数式接口。函数式接口就是只有一个抽象方法的接口。这样,就不难理解了,原来Lambda表达式只支持函数式接口。

4. Lambda表达式使用的几种方式

1
package com.wangjun.othersOfJava;
2
3
public class LambdaTest {
4
5
public static void main(String[] args) {
6
7
// 带类型
8
Animal a1 = (String str) -> {
9
System.out.println("狗狗吃饭:" + str);
10
};
11
// 不带类型
12
Animal a2 = (str) -> {
13
System.out.println("狗狗吃饭:" + str);
14
};
15
// 不带括号
16
Animal a3 = str -> {
17
System.out.println("狗狗吃饭:" + str);
18
};
19
// 不带大括号
20
Animal a4 = str -> System.out.println("狗狗吃饭:" + str);
21
a1.eat("火腿肠");
22
a2.eat("牛肉");
23
a3.eat("面条");
24
a4.eat("米饭");
25
26
// 使用return返回
27
Person p1 = () -> {
28
return "老师的职责:教书育人!";
29
};
30
// 直接返回
31
Person p2 = () -> "医生的职责:救死扶伤!";
32
System.out.println(p1.duty());
33
System.out.println(p2.duty());
34
}
35
36
// 没有返回值
37
interface Animal {
38
public void eat(String str);
39
}
40
// 有返回值
41
interface Person {
42
public String duty();
43
}
44
}
Copied!

4. Java的双冒号表达式

JDK8中有双冒号的用法,就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下。下面通过遍历一个List来说明一下双冒号和Lambda表达式使用方式的不同。
1
package com.wangjun.othersOfJava;
2
3
import java.util.Arrays;
4
import java.util.List;
5
import java.util.function.Consumer;
6
7
public class LambdaTest {
8
9
public static void printStr(String str) {
10
System.out.println(str);
11
}
12
13
public static void main(String[] args) {
14
15
List<String> list = Arrays.asList("aaa","bbb","ccc");
16
// 1.通常的遍历方式
17
for(String str: list) {
18
LambdaTest.printStr(str);
19
}
20
// 2.使用Lambda表达式遍历
21
list.forEach(str -> {
22
LambdaTest.printStr(str);
23
});
24
// 3.使用::遍历
25
list.forEach(LambdaTest::printStr);
26
// 下面的方法和上面等价,使用的是函数式编程
27
Consumer<String> methodParam = LambdaTest::printStr; //方法参数
28
list.forEach(x -> methodParam.accept(x));//方法执行accept
29
}
30
}
Copied!
Last modified 1yr ago