When using the reduce() operation on a parallel stream, the OCP exam book states that there are certain principles the reduce() arguments must adhe
Let me give two examples. First where the identity is broken:
int result = Stream.of(1, 2, 3, 4, 5, 6)
.parallel()
.reduce(10, (a, b) -> a + b);
System.out.println(result); // 81 on my run
Basically you have broken this rule: The identity value must be an identity for the accumulator function. This means that for all u, accumulator(identity, u) is equal to u.
Or to make is simpler, let's see if that rule holds for some random data from our Stream:
Integer identity = 10;
BinaryOperator combiner = (x, y) -> x + y;
boolean identityRespected = combiner.apply(identity, 1) == 1;
System.out.println(identityRespected); // prints false
And a second example:
/**
* count letters, adding a bit more all the time
*/
private static int howMany(List tokens) {
return tokens.stream()
.parallel()
.reduce(0, // identity
(i, s) -> { // accumulator
return s.length() + i;
}, (left, right) -> { // combiner
return left + right + left; // notice the extra left here
});
}
And you invoke this with:
List left = Arrays.asList("aa", "bbb", "cccc", "ffffffffd", "eeeeee");
List right = Arrays.asList("aa", "bbb", "cccc", "ffffffffd", "eeeeee", "");
System.out.println(howMany(left)); // 38 on my run
System.out.println(howMany(right)); // 50 on my run
Basically you have broken this rule: Additionally, the combiner function must be compatible with the accumulator function or in code :
// this must hold!
// combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
Integer identity = 0;
String t = "aa";
Integer u = 3; // "bbb"
BiFunction accumulator = (Integer i, String s) -> i + s.length();
BinaryOperator combiner = (left, right) -> left + right + left;
int first = accumulator.apply(identity, t); // 2
int second = combiner.apply(u, first); // 3 + 2 + 3 = 8
Integer shouldBe8 = accumulator.apply(u, t);
System.out.println(shouldBe8 == second); // false