fasth
fasth

Reputation: 2342

Stream works on sequential, but buggy in parallel mode

Currently I am reading a Java 8 Lambdas: Pragmatic Functional Programming (very interesting and well written book, no adv.).

After chapter 6 there is an exercise:

The code multiplies every number in a list together and multiplies the result by 5. This works fine sequentially, but has a bug when running in parallel.

public static int multiplyThrough(List<Integer> linkedListOfNumbers) {
    return linkedListOfNumbers.parallelStream()
                       .reduce(5, (acc, x) -> x * acc);
}

And solution:

public static int multiplyThrough(List<Integer> numbers) {
    return 5 * numbers.parallelStream()
                      .reduce(1, (acc, x) -> x * acc);
}

I don't understand why first approach is buggy in parallel mode and there is no explanation in the book.

Please, explain.

Upvotes: 2

Views: 148

Answers (1)

JB Nizet
JB Nizet

Reputation: 691755

The javadoc says:

The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t. The accumulator function must be an associative function.

This is clearly not the case in your first example:

5 * x is not equal to x.

The reason it doesn't give the same result in parallel mode is that, in this mode, the stream is splitted in chunks, and the reduction is applied for each chunk, and the results of each chunk are then reduced. So you end up multiplying by 5 several times, whereas in the sequential mode, the multiplication by 5 happens only once.

Upvotes: 6

Related Questions