Reduce with identity combiner parallel stream

Viewed 525
final Stream<Integer> numbers = Stream.of(5, 3, 2, 7, 3, 13, 7).parallel();

Why the output of the following line is 7?

 numbers.reduce(1, (a, b) -> a + b, (x, y) -> x - y)); 
1 Answers

I have not looked at that link from the comments, but the documentation is pretty clear about identity and it even provides a simple way of testing that:

The identity value must be an identity for the combiner function. This means that for all u, combiner(identity, u) is equal to u

So let's simplify your example a bit:

Stream<Integer> numbers = Stream.of(3, 1).parallel();
BiFunction<Integer, Integer, Integer> accumulator = (a, b) -> a + b;

BiFunction<Integer, Integer, Integer> combiner = (x, y) -> x - y; 

    int result = numbers.reduce(
            1,
            accumulator,
            combiner);

    System.out.println(result);

let's say that u = 3 (just a random element from the Stream), thus:

    int identity = 1;
    int u = 3;

    int toTest = combiner.apply(identity, u);
    System.out.println(toTest == identity); // must be true, but is false

Even if you think that you would replace identity with zero, that would work; the documentation makes another argument:

Additionally, combiner function must be compatible with the accumulator function; for all u and t, the following must hold:

 combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)

You can make the same test:

int identity = 0;
int u = 3;
int t = 1;

boolean associativityRespected = 
     combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t);
System.out.println(associativityRespected); // prints false
Related