我认为软件包摘要中的减少操作段落可以回答这个问题。让我在这里引用最重要的部分:java.util.stream
在其更一般的形式中,对生成类型结果的类型元素的 reduce 运算需要三个参数:<T>
<U>
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
此处,标识元素既是缩减的初始种子值,也是默认结果(如果没有输入元素)。累加器函数采用部分结果和下一个元素,并生成新的部分结果。合并器函数将两个部分结果组合在一起以生成新的部分结果。(在并行约简中,合并器是必需的,其中输入被分区,为每个分区计算部分累积,然后将部分结果组合以产生最终结果。更正式地说,标识值必须是组合器函数的标识。这意味着对于所有 ,等于 。此外,合路器函数必须是结合的,并且必须与累加器函数兼容:对于 all 和 ,必须为 。u
combiner.apply(identity, u)
u
u
t
combiner.apply(u, accumulator.apply(identity, t))
equals()
accumulator.apply(u, t)
三参数形式是两个参数形式的推广,将映射步骤合并到累积步骤中。我们可以使用更通用的形式重新转换简单的权重和示例,如下所示:
int sumOfWeights = widgets.stream()
.reduce(0,
(sum, b) -> sum + b.getWeight())
Integer::sum);
尽管显式 map-reduce 形式更具可读性,因此通常应该是首选。广义形式适用于可以通过组合映射和简化为单个函数来优化重要工作的情况。
换句话说,据我所知,三参数形式在两种情况下是有用的:
- 当并行执行很重要时。
- 当可以通过组合映射和累积步骤来实现显着的性能优化时。否则,可以使用更简单和可读的显式 map-reduce 表单。
显式表单在同一文档中前面提到过:
int sumOfWeights = widgets.parallelStream()
.filter(b -> b.getColor() == RED)
.mapToInt(b -> b.getWeight())
.sum();