一起来学Java8(二)——Lambda表达式

225 阅读5分钟

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表达式。