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

Brian Goetz brian.goetz at oracle.com
Fri Jun 14 12:12:00 PDT 2013


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