I\'m having trouble fully understanding the role that the combiner fulfils in Streams reduce method.
For example, the following code doesn
Since I like doodles and arrows to clarify concepts... let's start!
Suppose having 4 strings: your goal is to concatenate such strings into one. You basically start with a type and finish with the same type.
You can achieve this with
String res = Arrays.asList("one", "two","three","four")
.stream()
.reduce("",
(accumulatedStr, str) -> accumulatedStr + str); //accumulator
and this helps you to visualize what's happening:
The accumulator function converts, step by step, the elements in your (red) stream to the final reduced (green) value. The accumulator function simply transforms a String object into another String.
Suppose having the same 4 strings: your new goal is to sum their lengths, and you want to parallelize your stream.
What you need is something like this:
int length = Arrays.asList("one", "two","three","four")
.parallelStream()
.reduce(0,
(accumulatedInt, str) -> accumulatedInt + str.length(), //accumulator
(accumulatedInt, accumulatedInt2) -> accumulatedInt + accumulatedInt2); //combiner
and this is a scheme of what's happening
Here the accumulator function (a BiFunction) allows you to transform your String data to an int data. Being the stream parallel, it's splitted in two (red) parts, each of which is elaborated independently from eachother and produces just as many partial (orange) results. Defining a combiner is needed to provide a rule for merging partial int results into the final (green) int one.
What if you don't want to parallelize your stream? Well, a combiner needs to be provided anyway, but it will never be invoked, given that no partial results will be produced.