问题是关于 java.util.stream.Stream.reduce(U identity,BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
方法。
其中一个要求是combiner函数必须与accumulator函数兼容;对于所有 u 和 t,必须满足以下条件:
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t) (*)
如果combiner
和accumulator
相同,则上述等式自动成立。
一个BinaryOperator
实际上是扩展 BiFunction,因此我可以在 BiFunction
时使用它是必须的。如果 U 和 T 相同,则以下始终合法:
operator<T> op = (x,y) -> something;
stream.reduce(id, op, op);
当然,人们不能总是使用 combiner
如acumulator
因为在一般情况下,它们有不同的用途并且是不同的 Java 类型。
我的问题
是否有一个具有不同 combiner
的流减少示例和accumulator
?
此外,我对琐碎的示例不感兴趣,而是对并行流减少时在实践中遇到的自然示例感兴趣。
对于简单的例子,有很多教程,例如this one
我为什么问这个问题
基本上,这种缩减方法存在的原因是为了并行流。在我看来,条件(*)是如此强大,以至于在实践中,它使得这种归约毫无用处,因为归约操作很少满足它。
最佳答案
组合器和累加器是否相同?你在这里混淆了事情。
accumulator
从 X
转换至Y
例如(使用身份),而 combiner
合并两个Y
合而为一。另请注意,其中一个是 BiFunction
另一个是 BinaryOperator
(实际上是 BiFunction<T, T, T>
)。
Is there an example of stream reduction with distinct combiner and accumulator?
这些对我来说看起来很不同:
Stream.of("1", "2")
.reduce(0, (x, y) -> x + y.length(), Integer::sum);
我认为您可能会对以下内容感到困惑:
Stream.of("1", "2")
.reduce("", String::concat, String::concat);
怎么办?
BiFunction<String, String, String> bi = String::concat;
嗯,有一个 hint here 。
编辑
解决“不同”意味着不同操作的部分,accumulator
可能sum
,而accumulator
可能multiply
。这正是规则:
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
是为了保护自己免受两个独立关联函数的影响,但操作不同。让我们以两个列表(相等,但顺序不同)为例。顺便说一句,如果有 Set::of
会更有趣。来自java-9
添加 an internal randomization ,因此理论上来说,对于相同的输入,您在同一虚拟机上每次运行都会得到不同的结果。但为了简单起见:
List.of("a", "bb", "ccc", "dddd");
List.of("dddd", "a", "bb", "ccc");
我们想要执行:
....stream()
.parallel()
.reduce(0,
(x, y) -> x + y.length(),
(x, y) -> x * y);
在当前实现下,这将为两个列表产生相同的结果;但这是一个实现工件。
没有什么可以阻止内部实现:“我会将列表拆分为可能的最小块,但每个 block 中不小于两个元素”。在这种情况下,这可以转换为这些分割:
["a", "bb"] ["ccc", "dddd"]
["dddd", "a" ] ["bb" , "ccc" ]
现在,“累积”这些分割:
0 + "a".length = 1 ; 1 + "bb".length = 3 // thus chunk result is 3
0 + "ccc".length = 3 ; 3 + "dddd".length = 7 // thus chunk result is 7
现在我们“组合”这些 block :3 * 7 = 21
.
我很确定您已经看到在这种情况下第二个列表将导致 25
;因此累加器和组合器中的不同操作可能会导致错误的结果。
关于java - 使用不同的组合器和累加器进行流缩减的示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58980110/