Lambda简介
什么是Lambda表达式,简单的说是一种匿名函数表达方式。因此Lambda表达式本质是个函数,只不过没有函数名称。
Lambda表达式具有以下特点:
-
匿名,它没有函数名称
-
本质是个函数,除了函数名,它有参数列表、函数内容(方法体)、返回类型
-
简洁,有时候可以省略参数的类型
-
可传递,Lambda表达式可以当做一个变量进行存储
Lambda的基本语法是:
(参数列表) -> 表达式
或
(参数列表) -> { 表达式; }
哪里可以使用Lambda
有函数式接口的地方就可以使用Lambda表达式。
函数式接口的定义:一个接口里面只有一个抽象方法。 拿Runnable接口来说,它是一个函数式接口,Runnable用法如下代码所示:
1Thread thread = new Thread(new Runnable() {
2 @Override
3 public void run() {
4 System.out.println("run...");
5 }
6});
7thread.start();
8Thread.sleep(100);
由于Runnable是个函数式接口,因此可以使用Lambda表示替换,替换后如下:
1// 方式2
2Thread thread2 = new Thread(() -> System.out.println("run2..."));
3thread2.start();
4Thread.sleep(100);
这里的Lambda表达式内容即为:() -> System.out.println("run2..."),其中没有参数,没有返回值,只有一个方法体。这个表达式同样可以写成:
1Thread thread2 = new Thread(() -> {
2 System.out.println("run2..."); // 注意这里;结尾
3});
注意:加了花括号,方法体内部语句必须要有;结尾
还有一个函数式接口Callable,其内部的call方法需要返回一个值,Callable的使用方式如下代码所示:
1ExecutorService excutorService = Executors.newSingleThreadExecutor();
2Future<String> future = excutorService.submit(new Callable<String>() {
3 @Override
4 public String call() throws Exception {
5 return "Jim";
6 }
7});
8String name = future.get();
9System.out.println(name);
使用Lambda表达式:
1ExecutorService excutorService = Executors.newSingleThreadExecutor();
2Future<String> future = excutorService.submit(() -> "Jim2");
3String name = future.get();
4System.out.println(name);
这里() -> "Jim2"表示直接返回一个Jim2字符串,可以省略return关键字。当然也可以写成:
1excutorService.submit(() -> {
2 return "Jim2";
3});
下面我们自定义一个函数式接口,然后使用Lambda表达式来书写。
1package learn.java8.ch2;
2
3// 函数式接口
4@FunctionalInterface
5interface Caller {
6 String call(String name);
7}
8
9class Serivce {
10 private String name;
11
12 public Serivce(String name) {
13 this.name = name;
14 }
15
16 public String run(Caller caller) {
17 return caller.call(name);
18 }
19}
20
21public class LambdaTest2 {
22
23 public static void main(String[] args) {
24 Serivce service = new Serivce("Jim");
25 String result = service.run((name) -> {
26 return "My name is " + name;
27 });
28 System.out.println(result);
29 }
30
31}
此时Lambda表达式为:
1(name) -> {
2 return "My name is " + name;
3}
它具有参数列表、方法体、返回结果组成
注意:name实际类型被省略了,可以加上:
1String result = service.run((String name) -> {
2 return "My name is " + name;
3});
如果有多个参数,则写成:
(String a, String b) -> {} 或 (a, b) -> {}
Lambda表达式还可以当做变量进行存储,如下代码所示:
1package learn.java8.ch2;
2
3import java.util.function.Consumer;
4
5public class LambdaTest3 {
6
7 static Consumer<String> consumer = (name) -> {
8 System.out.println("My name is " + name);
9 };
10
11 static class Service {
12 private String name;
13
14 public Service(String name) {
15 super();
16 this.name = name;
17 }
18
19 public void run(Consumer<String> consumer) {
20 consumer.accept(name);
21 }
22 }
23
24 public static void main(String[] args) {
25 // 可以直接调用
26 consumer.accept("Jim");
27
28 new Service("Tom").run(consumer);
29 }
30
31}
在这个例子中直接使用Lambda表达式定义了一个接口实现:
1static Consumer<String> consumer = (name) -> {
2 System.out.println("My name is " + name);
3};
可以理解为将Lambda表达式赋给了consumer变量当中,也可以理解为直接实现了Consumer接口中的方法。
总之,只要有函数式接口的地方都可以使用Lambda表达式。