Why does Stream<T> not implement Iterable<T>?

In Java 8 we have the class Stream<T>, which curiously have a method

Iterator<T> iterator()

So you would expect it to implement interface Iterable<T>, which requires exactly this method, but that's not the case.

When I want to iterate over a Stream using a foreach loop, I have to do something like

public static Iterable<T> getIterable(Stream<T> s) {
    return new Iterable<T> {
        @Override
        public Iterator<T> iterator() {
            return s.iterator();
        }
    };
}

for (T element : getIterable(s)) { ... }

Am I missing something here?


Solution 1:

People have already asked the same on the mailing list ☺. The main reason is Iterable also has a re-iterable semantic, while Stream is not.

I think the main reason is that Iterable implies reusability, whereas Stream is something that can only be used once — more like an Iterator.

If Stream extended Iterable then existing code might be surprised when it receives an Iterable that throws an Exception the second time they do for (element : iterable).

Solution 2:

To convert a Stream to an Iterable, you can do

Stream<X> stream = null;
Iterable<X> iterable = stream::iterator

To pass a Stream to a method that expects Iterable,

void foo(Iterable<X> iterable)

simply

foo(stream::iterator) 

however it probably looks funny; it might be better to be a little bit more explicit

foo( (Iterable<X>)stream::iterator );