Loose end: spliterator() and stream() methods on Iterable

Brian Goetz brian.goetz at oracle.com
Mon Jun 24 12:40:36 PDT 2013

After further thought, I think what this means is that we can move 
spliterator() up to Iterable, but not stream().  The reason for this is 
that some classes that implement Iterable<Integer> might prefer that 
their stream() method return an IntStream, not be forced into a 
Stream<Integer>.  So putting stream() too high up in the hierarchy 
forecloses on this.

On 6/14/2013 3:12 PM, Brian Goetz wrote:
> In trying to work this one out, I ran into a snag with our test code.
> We have some test code that looks like:
> public interface TestData<T, S extends BaseStream<T, S>>
>          extends Iterable<T> {
>      S stream();
>      S parallelStream();
>      ...
> }
> with specializations:
>      public interface OfRef<T> extends TestData<T, Stream<T>> { }
>      public interface OfInt extends TestData<Integer, IntStream> { }
>      ...
> The idea is that the stream() method on TestData.OfRef returns a
> Stream<T>, and on a TestData.OfInt it returns an IntStream.  With stream
> methods on Iterable, this causes a conflict.
> Of course, I can change my test code.  But it illustrates the danger of
> adding stuff to "top-level" interfaces like Iterable -- the risk for
> conflict increases dramatically because so many things implement it.
> Here, the root cause is that I want stream() to be a type-specific
> method.  This definitely falls into the "advanced generics tricks"
> category, but being able to do this definitely reduced a lot of
> duplication in our code base, and I can't imagine I'm the only one who
> might want to do it.
> On 6/10/2013 6:19 PM, Brian Goetz wrote:
>> This is one that everyone seems in agreement with (in theory) but which
>> we never get to convergence on.  Given how the API has shaken out, it
>> seems sensible to:
>>   - Add spliterator() to Iterator, with a default implementation of
>>     return Spliterators.spliteratorUnknownSize(iterator(), 0)
>>   - Move the existing stream() and parallelStream() methods up from
>> Collection to Iterable, as is (they are implemented entirely in terms of
>> spliterator() and public factories)
>> When this last came up, there was concern that the spec of
>> Iterable.stream() would be exactly as fuzzy as the spec of
>> Iterable.iterator().  I think the best we can do is add an
>> implementation note that if iterator() indeed gives you a fresh iterator
>> every time, then stream() gives you a fresh stream every time, and
>> otherwise unpredictable results will follow.  It would be nice to
>> further note that subtypes of Collection are better behaved, but sadly
>> the spec for iterator() in Collection is no better than in Iterator!  We
>> can further add a "recommendation" to Iterable.iterator() to suggest
>> that Iterable implementations are encouraged to do this, but otherwise I
>> think this ship has sailed.

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