Why is the Java 8 ‘Collector’ class designed in this way?

Actually it was originally designed similarly to what you propose. See the early implementation in project lambda repository (makeResult is now supplier). It was later updated to the current design. I believe, the rationale of such update is to simplify collector combinators. I did not find any specific discussion on this topic, but my guess is supported by the fact that mapping collector appeared in the same changeset. Consider the implementation of Collectors.mapping:

public static <T, U, A, R>
Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
                           Collector<? super U, A, R> downstream) {
    BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
    return new CollectorImpl<>(downstream.supplier(),
                               (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
                               downstream.combiner(), downstream.finisher(),
                               downstream.characteristics());
}

This implementation needs to redefine accumulator function only, leaving supplier, combiner and finisher as is, so you don’t have additional indirection when calling supplier, combiner or finisher: you just call directly the functions returned by the original collector. It’s even more important with collectingAndThen:

public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
                                                            Function<R,RR> finisher) {
    // ... some characteristics transformations ...
    return new CollectorImpl<>(downstream.supplier(),
                               downstream.accumulator(),
                               downstream.combiner(),
                               downstream.finisher().andThen(finisher),
                               characteristics);
}

Here only finisher is changed, but original supplier, accumulator and combiner are used. As accumulator is called for every element, reducing the indirection could be pretty important. Try to rewrite mapping and collectingAndThen with your proposed design and you will see the problem. New JDK-9 collectors like filtering and flatMapping also benefit from current design.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)