第 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 条: 谨慎使用流并行
不恰当地并行化流的代价可能是程序失败或性能灾难。使用并行流之前,请确保您的代码在并行运行时保持正确,并在实际情况下进行仔细的性能度量。