I am trying to understand this Java Stream method
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
The following code should give as a result 55 put instead 0 is printed out. Can someone explain to me what is wrong and how to change it so that 55 is printed?
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Create a supplier that returns a new mutable result container, in this case an Integer accumulator.
Supplier<Integer> supplier = () -> 0;
// Create an accumulator that adds the square of the current element to the result container.
BiConsumer<Integer, Integer> accumulator = (result, element) -> result += element * element;
// Create a combiner that adds two result containers together.
BiConsumer<Integer, Integer> combiner = (result1, result2) -> result1 += result2;
// Collect the results of the reduction operation into a single Integer value.
Integer sumOfSquares = numbers.stream()
.collect(supplier, accumulator, combiner);
System.out.println(sumOfSquares); // 55
You are working on ints/Integer which are not mutable. Thus both, the accumulator and the combiner don't alter the result. Thus is stays 0.
You can avoid this problem by using a mutable object like AtomicInteger to do the operations and use a finisher to convert it back to Integer:
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Create a supplier that returns a new mutable! result container, in this case an AtomicInteger accumulator.
Supplier<AtomicInteger> supplier = () -> new AtomicInteger(0);
// Create an accumulator that adds the square of the current element to the result container.
BiConsumer<AtomicInteger, Integer> accumulator = (result, element) -> result.getAndAdd(element * element);
// Create a combiner that adds two result containers together.
BinaryOperator<AtomicInteger> combiner = (result1, result2) -> {
result1.getAndAdd(result2.get());
return result1;
};
//Create a Finisher to get the Integer value
Function<AtomicInteger, Integer> finisher = AtomicInteger::get;
// Collect the results of the reduction operation into a single Integer value.
Integer sumOfSquares = numbers.stream().collect(Collector.of(supplier, accumulator, combiner, finisher));
System.out.println(sumOfSquares); // 55
}