Iterating Collections

Now that you have the fundamentals of collections firmly in mind, you need a way to iterate through collections. You can accomplish this using three types of iterator interfaces. The java.util.Enumeration, java.util.Iterator, and java.util.ListIterator interfaces are used to iterate through data objects in a collection. The collections themselves are responsible for implementing these interfaces and for providing the iterator for the caller. They do this using inner classes.

Three Iterators

In the JDK, there are three principle types of iterators. Understanding each of them will help you pick the best one for your particular programming task.

java.util.Enumeration

This is the oldest of the iterators. It allows you to iterate one way through a collection. Once you pass an element, you cannot go back to that element without getting a new enumeration. One problem with enumeration is that it has been replaced by the Iterator interface. The Collection and Map interfaces require the developer to implement an Iterator but not an Enumeration. Therefore, you probably won't use this interface often unless the collection classes are not available (for instance, during J2ME coding on some limited profiles).

java.util.Iterator

This interface is the replacement in the JDK 1.2+ collection class architecture. Not only does it provide the same functionality as an Enumeration, but it allows you to remove an element from the collection by calling Iterator.remove( ). However, using Iterator.remove( ) can cause some rather confusing code.

java.util.ListIterator

The ListIterator interface allows you to iterate backwards in a list as well as forwards. This iterator is available only on classes that implement the List interface.

Fail-Fast Iterators

Many collections provide a fail-fast iterator. Essentially, this means that the iterator is designed to fail if the user modifies the list during iteration. For example, consider the following code:

package oracle.hcj.collections;
public class SomeClass {
 protected void markPreferredCustomer(final String someCustomer) {
 Set set = new HashSet( );
 // . . . add items to the set. String element = null;
 Iterator iter = set.iterator( );
 while (iter.hasNext( )) {
 element = (String) iter.next( );
 // . . . perform some logic
 if (element.equals(someCustomer)) {
 set.add(new String("p->" + element));
 set.remove(element);
 }
 }
 }
}


With the emphasized lines, the developer tries to modify the set while the iteration is still ongoing. The result of such an attempt will be a ConcurrentModificationException. When you are iterating through a collection, you must use the iterator methods to manipulate the list. Also, the Iterator class allows you only to remove an item. This makes sense because iterators can iterate over many kinds of collections that often have different semantics for adding new elements. In the end, you are better off not using Iterator.remove( ). Instead, you should save the changes you want to make and execute them after iterating through the collection. Also, if your collection can be accessed by multiple threads, you should surround the whole process with a synchronized block to prevent one thread from attempting modifications while another is iterating.

      
Comments