Issue
I am trying to figure out what accumulator and combiner do in reduce
stream operation.
List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
int result = users.stream()
.reduce(0,
(partialAgeResult, user) -> {
// accumulator is called twice
System.out.println(MessageFormat.format("partialAgeResult {0}, user {1}", partialAgeResult, user));
return partialAgeResult + user.getAge();
},
(integer, integer2) -> {
// combiner is never called
System.out.println(MessageFormat.format("integer {0}, integer2 {1}", integer, integer2));
return integer * integer2;
});
System.out.println(MessageFormat.format("Result is {0}", result));
I notice that the combiner is never executed, and the result is 65.
If I use users.parallelStream()
then the combiner is executed once and the result is 1050.
Why stream
and parallelStream
yield different results? I don't see any side-effects of executing this in parallel.
What is the purpose of the combiner in the simple stream version?
Solution
The problem is here. You are multiplying and not adding in your combiner.
(integer, integer2) -> {
// combiner is never called
System.out.println(MessageFormat.format("integer {0}, integer2 {1}", integer, integer2));
return integer * integer2; //<----- Should be addition
});
The combiner is used to appropriately combine various parts of a parallel operation as these operations can perform independently on individual "pieces" of the original stream.
A simple example would be summing a list of elements. You could have a variety of partial sums in a parallel operation, so you need to sum the partial sums in the combiner to get the total sum (a good exercise for you to try and see for yourself).
Answered By - WJS
Answer Checked By - Willingham (JavaFixing Volunteer)