3-arg version 的签名是:
<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
它打算在以下一项(或两项)为真时使用:
- 结果类型 (
U) 与流元素类型 (T) 不同。
-
combiner 与 accumulator 不同。
如果这些都不正确,那么2-arg version 更好(更简单、更容易):
T reduce(T identity,
BinaryOperator<T> accumulator)
对于问题中显示的示例,使用 3-arg 版本没有任何优势。
具有不同类型的示例很多,例如查看其他答案。
类型相同但combiner 为accumulator 的示例适用于- 减号运算符:
List<Integer> intarr = Arrays.asList(10,20,30);
// Sequential processing doesn't use combiner: totsum = -60
Integer totsum = intarr.stream().reduce(0, (a,b) -> a - b, (a,b) -> a - b);
// Parallel processing with same combiner does work: totsum = -20
Integer totsum = intarr.parallelStream().reduce(0, (a,b) -> a - b);
Integer totsum = intarr.parallelStream().reduce(0, (a,b) -> a - b, (a,b) -> a - b);
// Parallel processing requires a different combiner: totsum = -60
Integer totsum = intarr.parallelStream().reduce(0, (a,b) -> a - b, (a,b) -> a + b);
那是因为通过并行处理,我们为该输入流获得了 3 个线程,所以代码变为:
thread1Result = accumulator.apply(0/*identity*/, 10); // = 0 - 10 = -10
thread2Result = accumulator.apply(0/*identity*/, 20); // = 0 - 20 = -20
thread3Result = accumulator.apply(0/*identity*/, 30); // = 0 - 30 = -30
// Bad combiner: (a,b) -> a - b
result = combiner.apply(thread1Result, thread2Result); // = -10 - -20 = +10
result = combiner.apply(result, thread3Result); // = +10 - -30 = -20
// Good combiner: (a,b) -> a + b
result = combiner.apply(thread1Result, thread2Result); // = -10 + -20 = -30
result = combiner.apply(result, thread3Result); // = -30 + -30 = -60