I try to understand how does the reduce()
method work in java-8.
For example I have this code:
public class App {
public static void main(String[] args) {
String[] arr = {"lorem", "ipsum", "sit", "amet"};
List<String> strs = Arrays.asList(arr);
int ijk = strs.stream().reduce(0,
(a, b) -> {
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
},
(a, b) -> {
System.out.println("Combiner");
return a * b;
});
System.out.println(ijk);
}
}
And the output is this:
Accumulator, a = 0, b = lorem
Accumulator, a = 5, b = ipsum
Accumulator, a = 10, b = sit
Accumulator, a = 13, b = amet
17
It is a sum of the length of these strings. And I see that the combiner is not accessed, so it will not multiply the numbers, it only adds the numbers.
But if I replace stream
with parallelStream
:
int ijk = strs.parallelStream().reduce(0,
(a, b) -> {
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
},
(a, b) -> {
System.out.println("Combiner");
return a * b;
});
System.out.println(ijk);
This is the output:
Accumulator, a = 0, b = ipsum
Accumulator, a = 0, b = lorem
Accumulator, a = 0, b = sit
Combiner
Accumulator, a = 0, b = amet
Combiner
Combiner
300
I see that the Accumulator and Combiner are accessed both, but only the multiplication is return. So what's happen with the sum?
You should read the documentation of reduce
that says:
Additionally, the 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)
In your case, you are breaking that law (doing a sum in accumulator
and multiplication in the combiner
), so the result you see for such an operation is really undefined and depends on how the Spliterator for the underlying source is implemented (don't do that!).
Besides, the combiner
is only called for a parallel stream.
Of course, your entire approach could be simplified to:
Arrays.asList("lorem", "ipsum", "sit", "amet")
.stream()
.mapToInt(String::length)
.sum();
If you are doing that just for learning purposes, a correct reduce
would be (to get the sum
):
strs.parallelStream()
.reduce(0,
(a, b) -> {
System.out.println("Accumulator, a = " + a + ", b = " + b);
return a + b.length();
},
(a, b) -> {
System.out.println("Combiner");
return a + b;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With