7

I am new to Java 8. I am learning stream API's reduce method. I am seeing a weird behavior with this code:

public class PrdefinedCollectors {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
        List<Integer> dataHolder = new ArrayList<Integer>();
        List<Integer> numbers = stream.reduce(dataHolder, 
            (List<Integer> dataStore, Integer data) -> {
                    System.out.println(data + " ->: " + dataStore);
                    dataStore.add(data);
                    return dataStore;
                },
            (List<Integer> listOne, List<Integer> listTwo) -> {
                    System.out.println("ListOne Data :" + listOne + " List Two data :" + listTwo);
                    listOne.addAll(listTwo);
                    return listOne;
                });

        System.out.println(numbers);
    }
}

Output:

1 ->: []
2 ->: [1]
3 ->: [1, 2]
4 ->: [1, 2, 3]
5 ->: [1, 2, 3, 4]
6 ->: [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]

My question is why combiner function not executing meaning why this line:

System.out.println("List One Data: " + listOne + " List Two data: " + listTwo);

...is not executed?

Lii
  • 11,553
  • 8
  • 64
  • 88
vicky
  • 2,119
  • 4
  • 18
  • 32

1 Answers1

9

That is because you are not using a parallelStream().

A combiner is only called for a parallel stream.

But that is not the only problem in your code, reduce is suppose to work with immutable data - your code, the way it is right now, will fail for a parallel stream. This would work for collect, but for reduce you need to change it to :

 List<Integer> numbers = stream
            .parallel()
            .reduce(
                    new ArrayList<>(),
                    (list, data) -> {
                        ArrayList<Integer> newList = new ArrayList<>(list);
                        newList.add(data);
                        return newList;
                    },

                    (left, right) -> {
                        ArrayList<Integer> newList = new ArrayList<>(left);
                        newList.addAll(right);
                        return newList;
                    });
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 2
    Reworded your answer a bit to make it more clear. You know how to do undo in case you dont like my changes I guess. – GhostCat Aug 30 '17 at 08:48