Add convenience collect methods to the Stream interface

Brian Goetz brian.goetz at oracle.com
Mon Dec 10 16:14:41 UTC 2018


As will surprise no one, this was extensively discussed during the 
development of the Streams API.  (Our default position on "convenience 
methods" is hostile.  While everyone sees the benefit of convenience 
methods (it's convenient!), most people don't see the cost, which 
includes the complexity for users to understand the model by looking at 
the API; having lots of ad-hoc convenience method obscures the 
underlying model, making it harder for everyone to learn or reason 
about.  That default position seems to stand up pretty well here, as the 
stream API is pretty well factored.)

Let's be honest: the "convenience" or concision of being able to say 
.toList() instead of .collect(toList()) is really small.  I don't think 
you'll be able to justify it by saying "but we do it a lot."  
(Digression: to whoever is about to say "then why `toArray()`?  Arrays 
are different; for better or worse, they're part of the language, and 
they lend themselves particularly poorly to the Collector API, and there 
are particular parallelization optimizations that are possible for 
arrays that can't be accessed through Collector.  End digression.)

It is possible, however, that one could justify `toList()` on the basis 
of _discoverability_.  (Though I'm having a hard time seeing any world 
where `toSet()` makes the cut.)  New users who approach streams will not 
easily be able to figure out how to materialize a list from a stream, 
even though this is an entirely reasonable and quite common thing to 
want to do.  Having to learn about `collect()` first is asking a lot of 
users who are still wrapping their heads around streams.  Not only would 
`toList()` be more discoverable, it would provide a path to discovery of 
the rest of the `collect()` API.  This is a point in its favor.

A significant downside of adding `toList()` is that by diluting the 
orthogonality of the existing API, it provides both incentive and 
justification for further dilution, leading to someplace we don't want 
to be.  (And, the cost of that falls heavily on the stewards, which in 
turn takes time away from far more valuable activities.)

Put it this way: imagine we have a budget of one convenience method in 
Stream for every five years.  Is this the one we want to spend the next 
five year's budget on?  (And, who of the proponents will volunteer to 
answer the next 200 "I have an idea for a stream method" mails, 
explaining that the budget is spent?)


So, summary:

  - I won't outright veto `toList`, as I would for almost all other 
"convenience" streams additions, because this one actually has a valid 
non-convenience argument;
  - But, it's still not a slam dunk.


On 12/9/2018 5:44 PM, Rob Griffin (rgriffin) wrote:
> Hi,
>
> I have raised an enhancement request (Incident Report 913453) about adding some convenience methods to the Stream interface that collect the stream and Pallavi Sonal asked me to start a thread here about that.
>
> More than 50% of our Stream collect calls use Collectors.toList() or Collectors.toSet() as arguments so I think it would be very handy if the Stream interface had default collectToList and collectToList and collectToMap methods.
>
> The advantages are:
> 	it would be easier to use code completion in IDEs. There are lot of classes starting with Collect so finding the Collectors class is a bit of a pain.
> 	one less method call in what is usually a long chain of calls.
>
> Regards,
>
> Rob Griffin
> Software Analyst, Spotlight on SQL Server
> Quest | R&D
> rob.griffin at quest.com
>



More information about the core-libs-dev mailing list