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.