Java Iterator – Why Do Iterator and ListIterator Point Between Elements?

iteratorjava

The Javadoc for ListIterator says:

A ListIterator has no current element; its cursor position always lies
between the element that would be returned by a call to previous() and
the element that would be returned by a call to next().

Why was Java's ListIterator implemented to point between elements rather than at a current element? It seems that this makes client code less readable when it has to repeatedly call getNext(), getPrevious(), so I assume there must be a good reason for the choice.

As a side note, I just wrote a little library called peekable-arraylist that extends ArrayList, Iterator, and ListIterator that provides a peekAtNext() and peekAtPrevious() methods implemented like:

  @Override public synchronized T peekAtNext() {
     T t = next();
     previous();
     return t;
  }

Best Answer

As far as I can tell, the reason can be found in the part of javadoc you didn't quote (emphasis below mine):

An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration...

You see, the intended purpose is to allow usage while list is being modified. Possible modifications apparently include removal of the elements.

Now think of what would happen if we remove an element that would be current() for iterator - assuming that iterator would have a notion of current element? In this context, the way to implement it without a notion of current element makes pretty good sense to me - because that way, iterator does not have to worry about elements removal.


It is important to note that javadoc does not require interface implementations to be thread safe.

  • Because of that, one should not expect correct handling of modifications done from different threads - for that, implementation would have to provide additional means to synchronize access, guarantee visibility etc as specified by Java Memory Model per JSR 133.

What ListIterator is capable of, is handling modifications done from the same thread when iterating. Not all the iterators are like that, ConcurrentModificationException javadocs specifically warn about this:

...Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception...