5.4 归约
“计算菜单中的总卡路里” 或 “菜单中卡路里最高的菜是哪一个”。此类查询需要将流中所有元素反复结合起来,得到一个值。这样的查询可以被归类为 归约操作。用函数式编程语言的术语来说,这称为 折叠(fold)。
5.4.1 元素求和(reduce
)
# 有初始值
T reduce(T identity, BinaryOperator<T> accumulator);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
int sum = numbers.stream().reduce(0, Integer::sum);
# 无初始值
Optional<T> reduce(BinaryOperator<T> accumulator);
Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));
[Q&A] 无初始值 为什么它返回一个Optional呢?
考虑流中没有任何元素的情况。reduce操作无法返回其和,因为它没有初始值。这就是为什么结果被包裹在一个Optional对象里,以表明和可能不存在。
5.4.2 最大值和最小值
Optional<Integer> max = numbers.stream().reduce(Integer::max);
Optional<Integer> min = numbers.stream().reduce(Integer::min);
Optional<Integer> min = numbers.stream().reduce((x, y) -> x < y ? x : y);
5.4.3 统计个数
int count = menu.stream().map(d -> 1).reduce(0, (a, b) -> a + b);
long count = menu.stream().count();
[Q&A]归约方法的优势
reduce的好处在于,这里的迭代被 内部迭代
抽象掉了,这让内部实现得以选择并行执行reduce操作。外部迭代式求和例子要更新共享变量sum,这不是那么容易并行化的。如果你加入了同步,很可能会发现线程竞争抵消了并行本应带来的性能提升! 可变的累加器模式对于并行化来说是死路一条 !!! 这种计算的并行化需要另一种办法: 将输入分块,分块求和,最后再合并起来
-----------------------------------------------------------------------------读书笔记摘自 书名:Java 8实战 作者:[英] Raoul-Gabriel Urma [意] Mario Fusco [英] Alan M