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-experts
mailing list