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