I am trying to understand how the reduce method in streams work.
Stream.of(1,2,3,4,5,6,7).reduce(new ArrayList<>(),
(List<Integer> l, Integer a) -> {l.add(a);return l;},
(List<Integer> l1, List<Integer> l2) -> {
System.out.println("l1 is" + l1 + "l2 is " + l2);
l1.addAll(l2);
return l1;
}).forEach(System.out::println);
The line System.out.println("l1 is" + l1 + "l2 is " + l2)
never gets printed.
I can understand what is happening in (List<Integer> l, Integer a) -> {l.add(a);return l;}
Can some one please explain why it is not printed ?
The java docs say function for combining two values, which must be compatible with the accumulator function
Thanks, Amar
It's only being called when the stream is parallel. In that case, the stream values are split in half (recursively), each half is reduced to a list, and then the two lists must be combined together.
Note that reduction is not supposed to mutate the values (the lists, in this case) received as argument. It's supposed to return a new value. That's what a mutable reduction (i.e. collect()
) is a much better choice in this case.
It has described in java.util.stream package summary as below:
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
The combiner function combines two partial results to produce a new partial result. (The combiner is necessary in parallel reductions, where the input is partitioned, a partial accumulation computed for each partition, and then the partial results are combined to produce a final result.)
the "necessary" imply if your stream is empty or contains only single element in the stream, the combiner
also never be called in a parallel stream.
So if you want to see "l1 is" + l1 + "l2 is " + l2
is printed, you should run it in a parallel stream, for example:
// v--- make the stream run in parallel
Stream.of(1,2,3,4,5,6,7).parallel().reduce(...).forEach(System.out::println);
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