Brian Goetz brian.goetz at
Thu Feb 21 08:27:01 PST 2013

On the other hand, a big argument in favor of this is the simplicity of 
building our spliterator() on iterator().  Having stream() have 
different behavior than iterator() would be weird.

The iterator() method might do one of:
  A: give you a fresh iterator every time
  B: give you the same iterator every time
  C: throw

With the implementation as proposed, the behavior of stream() in these 
cases would be:
  A: give you a fresh stream every time
  B: give you a fresh stream, but which end up sharing the common Iterator
  C: throw

B leads to unpredictable results, but no more nasty than any other case 
where B happens.

(Joe's idea is a good guideline for writing iterator() methods anyway, 
maybe we should put that into the doc as a suggestion, asking classes 
that don't behave this way to be polite and document their deviant 

On 2/21/2013 11:14 AM, Joe Bowbeer wrote:
> When this question was raised 2 weeks ago, you asked:
> ""
> Can we make our best attempt to specify better than
> Iterable.iterator() was?
> I haven't worked out how to say this yet, but the idea is:
> - If at all possible to ensure that each call to stream() returns an
> actual working and independent stream, you really really should do that.
> - If that's just not possible, the second call to stream() really really
> should throw ISE.
> ""
> Is this something we should address?  There was no discussion about this
> last time.
> On Feb 21, 2013 8:07 AM, "Kevin Bourrillion" <kevinb at
> <mailto:kevinb at>> wrote:
>     1. Yes please.
>     2. And this time I won't hijack the thread.
>     On Thu, Feb 21, 2013 at 7:44 AM, Brian Goetz <brian.goetz at
>     <mailto:brian.goetz at>> wrote:
>         Currently we define stream() and parallelStream() on Collection,
>         with defaults like:
>              default Stream<E> stream() {
>                  return
>                     () -> Streams.spliterator(iterator()__, size(),
>                                               Spliterator.SIZED),
>                     Spliterator.SIZED);
>              }
>         In other words, if a Collection does not override stream(), it
>         gets the stream based on the iterator.
>         It has been suggested that we could move stream/parallelStream()
>         up to Iterable.  They could use an almost identical default,
>         except that they don't know the SIZED flag.  (The default in
>         Collection would stay, so existing inheritors of the Collection
>         default wouldn't see any difference.  (This is why default
>         methods are virtual.))
>         Several people have asked why not move these to Iterable, since
>         some APIs return "Iterable" as a least-common-denominator
>         aggregate type, and this would allow those APIs to participate
>         in the stream fun.  There are also a handful of other types that
>         implement Iterable, such as Path (Iterable<Path>) and
>         DirectoryStream (where we'd added an entries() method, but that
>         would just then become stream()).
>         The sole downside is that it creates (yet another) external
>         dependency from java.lang.Iterable -- now to
>         Thoughts?
>     --
>     Kevin Bourrillion | Java Librarian | Google, Inc. |kevinb at
>     <mailto:kevinb at>

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