Java8 之 Lambda 表达式的使用

Java8 中新增加了对于 Lambda 表达式的支持,还添加了 Stream 接口,便于对集合对象功能的增强。能够极大的简化代码的编写并提高代码的可读性,提供的
并发编程模式能够充分利用多核计算,而且无需编写线程相关的代码。下面的内容将会给出使用新的 Lambda 语法对集合对象进行扩展使用。

什么是函数式接口?

以最常用的迭代操作来举例,在 Java8 之前,我们进行迭代一个集合需要这样做:

List numbers = Arrays.asList(100, 200, 300, 400);
for (Integer number : numbers) {
    System.out.println(number);
}

升级到 Java8 之后,使用 Lambda 表达式进行迭代:

numbers.forEach(number -> System.out.println(number));

甚至可以进一步简化代码:

numbers.forEach(System.out::println);

那么这个 forEach 方法是什么?为什么可以做到这一点呢?查看源码,发现 forEach 方法是来自 Iterable 接口的一个默认方法。它的源码如下:

default void forEach(Consumer action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

阅读源码不难发现,实际上 forEach 还是通过普通的 for 循环实现的。只不过它的方法签名需要传递一个 Consumer 接口。我们来看一下这个接口的代码:

@FunctionalInterface
public interface Consumer {
    void accept(T t);
}

@FunctionalInterface 注解声明了该接口是一个函数式接口,这一类函数式接口有且仅有一个方法,如果添加多个方法,会出现编译错误。我们将一个 Lambda 表达式
传递给方法时,编译器会将 Lambda 表达式转换成对应接口的匿名实现类。也就是说传递给 forEach 方法的是 Consumer 的匿名实现类。为了便于观察,
我们可以将 Lambda 展开成匿名类的写法:

List numbers = Arrays.asList(100, 200, 300, 400);
Consumer consumer = new Consumer() {
    @Override
    public void accept(Integer number) {
        System.out.println(number);
    }
};
numbers.forEach(consumer);

如何应用函数式接口?

java.util.function 包中定义了一系列和函数式编程相关的类与接口,针对基本数据类型的接口有以下几种:

  • Predicate -- 传入一个参数,返回一个 boolean 结果, 方法为 `boolean test(T t)``
  • Consumer -- 传入一个参数,无返回值,纯消费。 方法为 `void accept(T t)``
  • Function -- 传入一个参数,返回一个结果,方法为 `R apply(T t)``
  • Supplier -- 无参数传入,返回一个结果,方法为 T get()
  • UnaryOperator -- 一元操作符, 继承 Function,传入参数的类型和返回类型相同。
  • BinaryOperator -- 二元操作符, 传入的两个参数的类型和返回类型相同,继承 BiFunction

我们可以使用这些接口实现一些自己的函数式接口,还是以迭代为例,我们来自己实现一个 forEach 方法:

// 定义一个函数式接口 MyConsumer,接收一个泛型参数无返回值
@FunctionalInterface
public interface MyConsumer {
    void accept(T t);
}
// 定义一个自己的 forEach 方法,传入自己定义的函数式接口和需要迭代的集合
public class Demo {
    public static  void forEach(MyConsumer consumer, Collection collection) {
        for (T t : collection) {
            consumer.accept(t);
        }
    }
}
// 调用自己的 forEach 方法,打印集合元素
public static void main(String[] args) {
    List numbers = Arrays.asList(100, 200, 300);
    Demo.forEach(System.out::println, numbers);
}

你可能感兴趣的:(Java8 之 Lambda 表达式的使用)