Why is Java's Iterator not an Iterable?

Viewed 51385

Why does the Iterator interface not extend Iterable?

The iterator() method could simply return this.

Is it on purpose or just an oversight of Java's designers?

It would be convenient to be able to use a for-each loop with iterators like this:

for(Object o : someContainer.listSomeObjects()) {
    ....
}

where listSomeObjects() returns an iterator.

16 Answers

An iterator is stateful. The idea is that if you call Iterable.iterator() twice you'll get independent iterators - for most iterables, anyway. That clearly wouldn't be the case in your scenario.

For example, I can usually write:

public void iterateOver(Iterable<String> strings)
{
    for (String x : strings)
    {
         System.out.println(x);
    }
    for (String x : strings)
    {
         System.out.println(x);
    }
}

That should print the collection twice - but with your scheme the second loop would always terminate instantly.

Because an iterator generally points to a single instance in a collection. Iterable implies that one may obtain an iterator from an object to traverse over its elements - and there's no need to iterate over a single instance, which is what an iterator represents.

To avoid dependence on java.util package

According to the original JSR, An enhanced for loop for the Java™ Programming Language, the proposed interfaces:

  • java.lang.Iterable
  • java.lang.ReadOnlyIterator
    (proposed to be retrofitted onto java.util.Iterator, but apparently this never happened)

…were designed to use the java.lang package namespace rather than java.util.

To quote the JSR:

These new interfaces serve to prevent the dependency of the language on java.util that would otherwise result.


By the way, the old java.util.Iterable gained a new forEach method in Java 8+, for use with lambda syntax (passing a Consumer).

Here is an example. The List interface extends Iterable interface, as any list carries a forEach method.

List
.of ( "dog" , "cat" , "bird" )
.forEach ( ( String animal ) -> System.out.println ( "animal = " + animal ) );

For the sake of simplicity, Iterator and Iterable are two distinct concepts, Iterable is simply a shorthand for "I can return an Iterator". I think that your code should be:

for(Object o : someContainer) {
}

with someContainer instanceof SomeContainer extends Iterable<Object>

Related