Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the accumulator of reduce in Java 8 allowed to modify its arguments?

In Java 8, Stream has a method reduce:

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

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);

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.

like image 659
Graeme Moss Avatar asked May 26 '14 12:05

Graeme Moss


1 Answers

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.

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

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.)

like image 200
Brian Goetz Avatar answered Oct 05 '22 16:10

Brian Goetz