Add convenience collect methods to the Stream interface

Brian Goetz brian.goetz at
Tue Dec 11 14:05:01 UTC 2018

You say it jokingly, but we've explored this.  (The exact way you phrase 
it (the supertype specified to throw if called more than once) means 
that Iterable can't extend IterableOnce, because then Iterable does not 
conform to the superclass contract, but there are other ways to stack 
it.)  It's not completely unworkable, but as you've observed, it's not 
so clean.

In the JSR-335 EG, we also explored (and rejected, because it felt like 
the library tail wagging the language dog) the route of adding language 
support for more kinds of things on the RHS of the for-each loop.

(Zooming out: the main reason this is irritating is the limitations of 
what you can do in a method like .forEach() vs the foreach loop -- 
exception transparency, nonlocal return, up-scope local mutation.  
Though it is unlikely that we'll have great solutions for these all that 
soon, so its reasonable to consider library-based solutions in the 

On 12/11/2018 7:55 AM, Rachel Greenham wrote:
> Although I do understand the reasoning (non-repeatability of streams), 
> Stream not implementing Iterable is a minor but frequent annoyance for 
> this precise reason. Using forEach() instead isn't always an option.
> Maybe Iterable can have a superinterface IterableOnce with the methods 
> moved up to there, and iterator() specified to throw 
> IllegalStateException if called twice, and which enhanced-for 
> recognises, then Stream can implement that? (Ducks and runs...)
> Or enhanced-for can also take Supplier<Iterator>, so we can do 'for 
> (Thing e : stream::iterator)' instead of 'for (Thing e : 
> (Iterable<Thing>)stream::iterator)'
> (runs faster...)

More information about the core-libs-dev mailing list