Refactor of Collector interface

Kevin Bourrillion kevinb at
Fri Feb 8 08:22:00 PST 2013

My subjective sense of good Java API design very strongly prefers the
"before" picture here, which I see as a lot more "Java-like", so I'm taking
a closer look.

I assume that the trade-offs we're weighing here are purely to do with what
it's like to be a Collector implementor, correct?

On Fri, Feb 8, 2013 at 7:25 AM, Brian Goetz <brian.goetz at> wrote:

> FYI: In a recent refactoring, I changed:
> public interface Collector<T, R> {
>     R makeResult();
>     void accumulate(R result, T value);
>     R combine(R result, R other);
> }
> to
> public interface Collector<T, R> {
>     Supplier<R> resultSupplier();
>     BiConsumer<R, T> accumulator();
>     BinaryOperator<R> combiner();
> }
> Basically, this is a refactoring from typical interface to
> tuple-of-lambdas.  What I found was that there was a lot of adaptation
> going on, where something would start out as a lambda, we'd wrap it with a
> Collector whose method invoked the lambda, then take a method reference to
> that wrapping method and then later wrap that with another Collector, etc.
>  By keeping access to the functions directly, the Collectors code got
> simpler and less wrappy, since a lot of functions could just be passed
> right through without wrapping.  And a lot of stupid adapter classes went
> away.
> While clearly we don't want all interfaces to evolve this way, this is one
> where *all* the many layers of manipulations are effectively function
> composition, and exposing the function-ness made that cleaner and more
> performant.  So while I don't feel completely super-great about it, I think
> its enough of a win to keep.

Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at

More information about the lambda-libs-spec-observers mailing list