Using an Explicit Iterator on a Collection – Collections: Part II


Using an Explicit Iterator on a Collection

A collection provides an iterator which allows sequential access to the elements of a collection. An iterator can be obtained by calling the iterator() method of the Collection<E> interface. An iterator is defined by the generic interface java.util.Iterator<E> that has the following methods:

Click here to view code image

boolean hasNext()                               
From
 Iterator<E>
interface.

Returns true if the underlying collection still has elements left to return. A future call to the next() method will return the next element from the collection.

Click here to view code image

E next()                                        
From
 Iterator<E>
interface.

Moves the iterator to the next element in the underlying collection, and returns the current element. If there are no more elements left to return, it throws a NoSuchElementException.

Click here to view code image

void remove()               
Optional           From
 Iterator<E>
interface.

Removes the element that was returned by the last call to the next() method from the underlying collection. Invoking this method results in an Illegal-StateException if the next() method has not yet been called, or when the remove() method has already been called after the last call to the next() method. This method is optional for an iterator—that is, it throws an Unsupported-OperationException if the remove operation is not supported.

Click here to view code image

default void
    forEachRemaining(Consumer<? super E> action)
From
 Iterator<E>
interface.

The specified action is performed on each of the remaining elements in the collection associated with an iterator, unless an exception is thrown during its execution. The functional interface Consumer<T> is covered in §13.7, p. 709.

After obtaining the iterator for a collection, the methods provided by the Iterator<E> interface can be used systematically to iterate over the elements of the underlying collection one at a time.

In Example 15.1, an explicit iterator is obtained at (2) and used in the loop at (3) to iterate over all elements in the underlying collection. A call to the hasNext() method in the condition of the loop ensures that there is still an element to retrieve from the collection. At (4) the current element is retrieved by the iterator from the collection by calling the next() method. No casts are necessary at (4), as the compiler guarantees that the iterator will return a String object from the underlying collection.

Click here to view code image

Iterator<String> iterator = collectionOfNames.iterator();        // (2)
while (iterator.hasNext()) {                                     // (3)
  String name = iterator.next();                                 // (4)
  System.out.print(name.toUpperCase() + ” “);
}

Note that the methods are invoked on the iterator, not the underlying collection. In Example 15.1, the hasNext() method is called before the next() method to ensure that there is still an element remaining to be processed; otherwise, a java.util.NoSuchElementException can be raised at runtime. Using an explicit iterator puts this responsibility on the user code.

In Example 15.1, we used an iterator in a while loop at (3) for iterating over the collection. It is quite common to use an iterator in a for(;;) loop for this purpose, where the iterator is obtained in the initialization part, and the increment part is left empty:

Click here to view code image

for (Iterator<String> iterator = collectionOfNames.iterator();
     iterator.hasNext(); /* Empty increment. */) {
  String name = iterator.next();
  System.out.print(name.toUpperCase() + ” “);
}

The majority of the iterators provided in the java.util package are said to be fail-fast. When an iterator has already been obtained, structurally modifying the underlying collection by other means will invalidate the iterator. Subsequent use of this iterator will throw a ConcurrentModificationException, as the iterator checks to see if the collection has been structurally modified every time it accesses the collection. The remove() method of an iterator is the only recommended way to delete elements from the underlying collection during iteration with an iterator (p. 796).

The order in which the iterator will return the elements from an underlying collection depends on the iteration order supported by the collection. For example, an iterator for a list will iterate over the elements in the sequential order they have in the list, whereas the iteration order for the elements in an ordinary set is not predetermined. An iterator for a sorted collection will make the elements available in a given sort order. Iteration order will be discussed together with the individual concrete collection classes.

Leave a Reply

Your email address will not be published. Required fields are marked *