06 Lambdas 与 Streams(42-48)

Wu Jun 2020-01-02 15:51:26
05 Java > 02 Effective Java

第 42 条:lambdas 优于匿名类

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

lambda 没有名称和文档,如果超过三行,不要使用 lambda 表达式。

第 43 条: 方法引用优于 lambdas

如果方法引用看起来更简短更清晰,请使用它们;否则,还是坚持 lambda。

方法引用类型 举例 等同的 Lambda
Static Integer::parseInt str -> Integer.parseInt(str)
Bound Instant.now()::isAfter Instant then = Instant.now(); t -> then.isAfter(t)
Unbound String::toLowerCase str -> str.toLowerCase()
Class Constructor TreeMap<K,V>::new () -> new TreeMap<K,V>
Array Constructor int[]::new len -> new int[len]

第 44 条: 优先使用标准的函数式接口

设计API时必须考虑 lambda 表达式。 在输入上接受函数式接口类型并在输出中返回它们。 一般来说,最好使用 java.util.function.Function 中提供的标准接口

接口 方法 示例 表示
UnaryOperator T apply(T t) String::toLowerCase 方法的结果和参数类型相同
BinaryOperator T apply(T t1, T t2) BigInteger::add 方法的结果和参数类型相同
Predicate boolean test(T t) Collection::isEmpty 方法接受一个参数并返回一个布尔值
Function<T,R> R apply(T t) Arrays::asList 参数和返回类型不同
Supplier T get() Instant::now 一个不接受参数和返回值(或“供应”)的方法
Consumer void accept(T t) System.out::println 接受一个参数而不返回任何东西

第 45 条: 明智审慎地使用 Stream

在没有显式类型的情况下,仔细命名 lambda 参数对于流管道的可读性至关重要。

使用辅助方法对于流管道中的可读性比在迭代代码中更为重要

重构现有代码以使用流,并仅在有意义的情况下在新代码中使用它们。

如果不确定一个任务是通过流还是迭代更好地完成,那么尝试这两种方法,看看哪一种效果更好。

第 46 条: 优先考虑流中无副作用的函数

第 47 条: 返回类型优先选择集合而不是流

如果返回集合是可行的,请执行此操作。如果返回集合是不可行的,则返回流或可迭代的。

如果在将来的 Java 版本中,Stream 接口声明被修改为继承 Iterable,那么可随意返回流。

第 48 条: 谨慎使用流并行

不恰当地并行化流的代价可能是程序失败或性能灾难。使用并行流之前,请确保您的代码在并行运行时保持正确,并在实际情况下进行仔细的性能度量。