Refactor of Collector interface

Brian Goetz brian.goetz at oracle.com
Fri Feb 8 08:39:46 PST 2013


> Hmm, it's difficult for me to perceive what these benefits are from
> looking at the change to Collectors.java
> <http://hg.openjdk.java.net/lambda/lambda/jdk/diff/221c5b4f706c/src/share/classes/java/util/stream/Collectors.java>,
> and the file did get 70 lines longer as a result of the change fwiw, and
> seems to rely more on private abstract base classes that other Collector
> implementors won't have.

It actually got smaller when this transform was applied, but more stuff 
went into Collectors in the same changeset, such as the mapped() 
combinators.

I have no objection to making that abstract base class public if that's 
a concern, though it's not really necessary since Collector writers can 
do without it:

class FooCollector implements Collector {
     Supplier<R> resultSupplier() { return Foo:: new; }
     ...
}

The abstract class is mostly there as a "fake tuple" class for 
convenience of the Collectors implementation, and I think we're on 
record as saying that it is reasonable to expect users to write their 
own fake tuple classes.

> (How do you get to side-by-side diff in this thing? I feel quite blind
> without it and am thus stuck in "I don't get it" mode.)
>
>
> On Fri, Feb 8, 2013 at 8:22 AM, Kevin Bourrillion <kevinb at google.com
> <mailto:kevinb at google.com>> wrote:
>
>     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 oracle.com
>     <mailto:brian.goetz at oracle.com>> 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 google.com
>     <mailto:kevinb at google.com>
>
>
>
>
> --
> Kevin Bourrillion | Java Librarian | Google, Inc. |kevinb at google.com
> <mailto:kevinb at google.com>


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