0%

Effective Java 第三版 (6) Lambdas 与 Stream

Lambdas 与 Stream

§ Lambda 表达式优于匿名类

1
2
3
4
5
Collections.sort(words, new Comparator<String>() { 
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});

Java 8 增加了函数式接口,lambda 表达式和方法引用,以便更容易地创建函数对象。Stream API 一同被添加进来,为处理数据元素序列提供类库支持。

从 Java 8 开始,lambda 是迄今为止表示小函数对象的最佳方式。 除非必须创建非函数式接口类型的实例,否则不要使用匿名类作为函数对象。

1
2
3
Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

Collections.sort(words, comparingInt(String::length));

§ 方法引用优于 lambda 表达式

Java 提供了一种生成函数对象的方法,比 lambda 还要简洁,那就是:方法引用。

1
2
3
map.merge(key, 1, (count, incr) -> count + incr);

map.merge(key, 1, Integer::sum);

只要方法引用能做的事情,就没有 lambda 不能完成的,使用方法引用通常会得到更短更清晰的代码。

如果使用 IDE,它一般会提供替换 lambda 的方法。

§ 优先使用标准的函数式接口

java.util.function 提供了大量标准函数式接口供使用。应该优先使用。

始终使用 @FunctionalInterface 注解标注你的函数式接口。

§ 谨慎的使用 Stream

Java 8 添加了 Stream API,以简化串行或并行执行批量操作的任务。该 API 提供了两个关键的抽象:

  • 流(Stream)。表示有限或无限的数据元素序列。
  • 流管道(Stream Pipeline)。表示对这些元素的多级计算。

Stream 的元素可以来自任何地方。包括集合、数组、文件、正则。流中的元素可以是对象引用或基本类型。支持三种基本类型:int, long, double

过度使用流使程序难于阅读和维护。因此,重构现有代码以使用流,并仅在有意义的情况下在新代码中使用它们。

§ 优先考虑流中无副作用的函数

§ 优先使用 Collection 而不是 Stream 来作为方法的返回类型

§ 谨慎的使用流并行