Does Iterable#iterator() return a new iterator or an existing one?

576 views Asked by At

Does calling anIterable.iterator() return a new or an existing Iterator? Does it depend on the Iterable implementation?

More specifically, would the following code work as expected (i.e. the inner loop would iterate from the beginning)?

for (Item itemA : items) {
    for (Item itemB : items) {
        ....
    }
}

If not, than how can this be achieved on an Iterable?

5

There are 5 answers

0
Srijan Mehrotra On

Depends how iterable interface is implemented. Generally the collection frameworl classes returns new instance.

0
Ankur Singhal On

Iterable

Iterable is the Interface, we need to provide implementation for iterator() method.

public class MyCollection<E> implements Iterable<E>{

    public Iterator<E> iterator() {
        return new MyIterator<E>();
    }
}

Implementation skeleton of the MyIterator class:

public class MyIterator <T> implements Iterator<T> {

    public boolean hasNext() {

        //implement...
    }

    public T next() {
        //implement...;
    }

    public void remove() {
        //implement... if supported.
    }
}

Using MyCollection generified, and with the new for-loop

public static void main(String[] args) {
    MyCollection<String> stringCollection = new MyCollection<String>();

    for(String string : stringCollection){

    }
}

For your 2nd question, output speaks, the inner loop will loop from the starting everytime.

public static void main(String[] args) {
        List<String> names = new ArrayList<String>();
        names.add("a1");
        names.add("a2");

        for (String itemA : names) {
            for (String itemB : names) {
                System.out.println("Inner => " + itemB);
            }
            System.out.println("Outer => " + itemA);
        }
    }

Inner => a1
Inner => a2
Outer => a1
Inner => a1
Inner => a2
Outer => a2

Refereed this for examples

0
Eran On

anIterable.iterator() should return a new iterator and in that case the nested enhanced for loops will work as expected. All standard implementations of Iterable return a new Iterator when iterator() is called.

If some bad implementation of the Iterable interface doesn't return a new Iterator in consecutive calls to iterator(), the nested enhanced for loops will break.

BTW, the Javadoc of Iterable's iterator() method doesn't require that it return a new Iterator.

0
Dmitry Ginzburg On

You may iterate the same collection in parallel, but you cannot modify it. So your code is completely correct: the new iterator would be returned each time.

0
Mena On

Iterable<T> is an interface, so there is no default implementation.

In ArrayList<T> for instance, the iterator<E> method will return a new instance of the nested class Itr each invocation:

public Iterator<E> iterator() {
    return new Itr();
}