Java 8中的reduce累加器是否允许修改其参数? [英] Is the accumulator of reduce in Java 8 allowed to modify its arguments?

查看:149
本文介绍了Java 8中的reduce累加器是否允许修改其参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java 8中,Stream有一个方法reduce:

In Java 8, Stream has a method reduce:

T reduce(T identity, BinaryOperator<T> accumulator);

累加器运算符是否允许修改其任一参数?我认为不是因为JavaDoc说累加器应该是NonInterfering,尽管所有的例子都谈到修改集合,而不是修改集合的元素。

Is the accumulator operator allowed to modify either of its arguments? I presume not since the JavaDoc says the accumulator should be NonInterfering, though all examples talk of modifying the collection, rather than modifying the elements of the collection.

所以,对于一个具体的例子,如果我们有

So, for a concrete example, if we have

 integers.reduce(0, Integer::sum);

并假设片刻整数是可变,将 sum 允许修改其第一个参数,方法是将其第二个参数的值加到(就地)?

and suppose for a moment that Integer was mutable, would sum be allowed to modify its first parameter by adding to it (in place) the value of its second parameter?

我认为没有,但我也想要一个关于这个干扰导致问题的例子。

I presume not, but I would also like an example of where this Interfering causes a problem.

推荐答案

没有。累加器不应修改其参数;它需要两个值并产生一个新值。如果你想在累积过程中使用变异(例如,将字符串累积到StringBuffer而不是连接),请使用 Stream.collect(),这是为此而设计的。

No. The accumulator should not modify its arguments; it takes two values and produces a new value. If you want to use mutation in the course of accumulation (e.g., accumulating strings into a StringBuffer instead of concatenating), use Stream.collect(), which is designed for this.

这是一个代码示例,如果您尝试这样做会产生错误的答案。假设您想要使用假设的MutableInteger类进行添加:

Here's an example of code that produces the wrong answer if you try this. Let's say you want to do addition with a hypothetical MutableInteger class:

// Don't do this
MutableInteger result = stream.reduce(new MutableInteger(0), (a,b) -> a.add(b.get()));

这得到错误答案的一个原因是,如果我们并行破解计算,现在进行两次计算共享相同的可变起始值。请注意:

One reason this gets the wrong answer is that if we break the computation up in parallel, now two computations are sharing the same mutable starting value. Note that:

a + b + c + d
= 0 + a + b + 0 + c + d  // 0 denotes identity
= (0 + a + b) + (0 + c + d) // associativity

所以我们可以自由拆分流,计算部分金额 0 + a + b 0 + c + d ,然后添加结果。但是如果它们共享相同的标识值,并且该值由于其中一个计算而发生变化,则另一个可能以错误的值开始。

so we are free to split the stream, compute the partial sums 0 + a + b and 0 + c + d, and then add the results. But if they are sharing the same identity value, and that value is mutated as a result of one of the computations, the other may start with the wrong value.

(进一步注意,即使对于顺序计算,也允许实现这样做,如果它认为值得的话。)

(Note further that the implementation would be allowed to do this even for sequential computations, if it thought that was worthwhile.)

这篇关于Java 8中的reduce累加器是否允许修改其参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆