Search code examples
javajava-stream

Java Stream Api: Using reduce to fill a collection


I am well aware of the collect() method and the Collectors object. However, I don't really understand why it's bad to use a reduce to populate a collection.

` User u1 = new User ("Tom");
User u2 = new User ("Anna");
User u3 = new User ("Alice");

    BiFunction<Set<String>, User, Set<String>> accumulator = (acc, u) -> {
        acc.add(u.getLogin());
        return acc;
    };
    BinaryOperator<Set<String>> combiner = (s1, s2) -> {
        s1.addAll(s2);
        return s2;
    };

    Stream<User> stream = Stream.of(u1, u2, u3);
    Set<String> logins = new HashSet<>();
    stream.reduce(logins, accumulator, combiner);
    System.out.println(logins);// [Tom, Alice, Anna]`

Is this bad code design, or something else under the hood?

Is it true that accumulation should be done on an immutable object?


Solution

  • According to the documentation:

    Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.

    It is much easier to parallelize calls to .collect and have a predictable order. On the other hand, the accumulator function passed to reduce should be associative and it may not be called on elements in the stream in encounter order, especially for parallel processing.

    Furthermore, the meaning of the collect operation is much clearer and it should be preferred when the intention is indeed to create a collection from the elements of the stream.