Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unexpected result calling collect method on a Java Stream

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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 Integer 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.set(result1.getAndAdd(result2.get()));
        return result1;
    };

    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
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading