Iterable and Iterator

We have now used two interfaces, and they are easy to confuse.

Iterable<T> has a single method, iterator(). It describes the data structure. If a structure implements Iterable, we can iterate over it, and its iterator() method returns an object that does the iterating. Our Set extends Iterable, so every set is iterable, and ArraySet implements iterator() by returning an iterator.

Iterator<T> has hasNext() and next(). It is the object that does the iterating. It holds the position in the traversal (for ArraySet, the cursor) and produces the elements one at a time. ArraySetIterator is that object.

So one interface is about the data structure, and the other is about a single traversal of it. The position is stored in the iterator object, not in the set, so each call to iterator() starts a fresh, independent traversal with its own cursor.

Because the traversals are independent, nested loops over the same set work. Suppose we want to compare every element with every other one:

for (T a : set) {
  for (T b : set) {
    // compare a and b
  }
}

Each loop calls set.iterator() and gets its own iterator with its own cursor, so the inner traversal does not disturb the outer one.