Collector / Collectors

Brian Goetz brian.goetz at
Thu Jun 27 14:31:16 PDT 2013

> 2.  Making the one-arg reducing(), and minBy/maxBy, return Optional
> means that queries like "tallest person by city" end up with Optional in
> the value:
>    Map<City, Optional<Person>> m
>      = people.collect(groupingBy(Person::getCity,
>                                  maxBy(comparing(Person::getHeight)));
> Which is doubly bad because the optionals here will *always* be present,
> since otherwise there'd be no associated key.
> I can see a few ways to address this:
>   - Provide non-optional versions of minBy/maxBy/reducing, which would
> probably have to return null for "no elements".
>   - Provide a way to add a finisher to a Collector, which is more
> general (and could be used, say, to turn toList() into something that
> always collects to an immutable list.)
> The latter could, in turn, be done in one of two ways:
>   - Add a andThen(f) method to Collector.  Then the above would read:
>     groupingBy(Person::getCity,
>                maxBy(comparing(Person::getHeight))
>                  .andThen(Optional::get))
>   - Add a combinator:
>     groupingBy(Person::getCity,
>                finishing(maxBy(comparing(Person::getHeight)),
>                          Optional::get)));
> I prefer the former because it reads better in usage; using a combinator
> function feels a little "inside out."

Having run into roadblocks with the andThen() approach, I'm thinking 
about the combinator approach.  But unlike the existing combinators 
(mapping, groupingBy, partitioningBy), it feels clunky.  I think this is 
largely a naming problem, because all the other combinators are "do 
something first and then use the specified Collector", but this is "use 
the specified Collector and then do something else."



reads kind of inside-out.  But maybe by making it slightly longer:


mitigates this problem?

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