Lambda表达式与函数式接口

Lambda表达式

java8中引入了Lambda表达式是函数式接口的一个匿名函数定义实现类,类似js里的闭包。

Lambda可以大大简化函数式接口的实现代码,可读性更好。 - ->左边: 函数传入的参数,编译器会自动推断参数类型,不需要显示指定。当只有一个参数时,可以省略() - ->右边: 函数执行的逻辑,如果只有一行代码,可以省略掉{},可以没有返回值。

ExecutorService pool = Executors.newSingleThreadExecutor();
CountDownLatch cdl = new CountDownLatch(2);

pool.submit(new Runnable() {
    @Override
    public void run() {
        System.out.println("java8之前的写法");
        cdl.countDown();
    }
});

pool.submit(() -> {
    System.out.println("Lambda表达式写法");
    cdl.countDown();
});

cdl.await();
pool.shutdown();

函数式接口

只有一个抽象方法的接口就是函数式接口,通常适用@FunctionalInterface注解来修饰。例如:Runnable、Comparator和Callable。也可以自定义一个函数式接口。

jdk已经定义了很多常用的函数式接口

函数式接口 抽象方法 说明
Consumer< T > void accept(T t) 消费接口,通常用来遍历处理数据
Supplier< T > T get() 供给接口,没有入参,返回一个对象
Function R apply(T t) 函数接口,需要一个入参,返回一个对象
Predicate< T > boolean test(T t) 断言接口,通常用来校验数据

除了这些之外还有很多多XxxConsumer, XxxSupplier, XxxFunction, XxxPredicate的函数式接口,基本上大同小异,只是参数个数不同。

示例

// Lambda创建一个比较器
Comparator<Integer> com = (o1, o2) -> o2 - o1;
List<Integer> list1 = Arrays.asList(1, 20, 30, 13, 40);
List<Integer> list2 = Arrays.asList(1, 20, 30, 13, 40);
list1.sort(com);
System.out.println(list1);

// 省去Comparator定义
list2.sort((o1, o2) -> o2 - o1);
System.out.println(list2);

Consumer<Integer> c1 = i -> {
    i = i * 2;
    System.out.println("i * 2 = " + i);
};
c1.accept(10);

Supplier<String> s1 = () -> "fjx" + Instant.now().toEpochMilli();
System.out.println(s1.get());

Function<Long, String> f1 = l -> "fjx" + l;
System.out.println(f1.apply(Instant.now().toEpochMilli()));

Predicate<String> p1 = str -> str == null;
System.out.println(p1.test("fjx"));