Tuesday 21 September 2010

Iterators

The List and Set collections provide iterators, which are objects that allow going over all the elements of a collection in sequence. The java.util.Iterator interface provides for one-way traversal and java.util.ListIterator provides two-way traversal. Iterator is a replacement for the older Enumeration class which was used before collections were added to Java.

Creating an Iterator

Iterators are created by calling the iterator() or listIterator() method of a List, Set, or other data collection with iterators.

public void showCollection ( Collection c )
{
    Iterator i = c.iterator();
   while ( i.hasNext() ) {  //returns true if elements are still there
Object o = i.next();         //returns the next element
// Process element, casting to
// appropriate type if necessary
}

Methods in Iterator Interface

Iterator defines three methods, one of which is optional.
ResultMethod Description
b = it.hasNext() true if there are more elements for the iterator.
obj = it.next() Returns the next object. If a generic list is being accessed, the iterator will return something of the list's type. Pre-generic Java iterators always returned type Object, so a downcast was usually required.
void it.remove() Removes the most recent element that was returned by next. Not all collections support delete. An UnsupportedOperationException will be thrown if the collection does not support remove().

Difference from Enumeration Interface

An Iterator is similar to the Enumeration interface, Iterators differ from enumerations in two ways:
1.Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
2. Method names have been improved.  


The hasNext method is identical in function to Enumeration.hasMoreElements, and the next method is identical in function to Enumeration.nextElement. The remove method removes from the underlying Collection the last element that was returned by next. The remove method may be called only once per call to next, and throws an exception if this condition is violated. Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

The following snippet shows you how to use an Iterator to filter a Collection, that is, to traverse the collection, removing every element that does not satisfy some condition:
static void filter(Collection c) {
for (Iterator i = c.iterator(); i.hasNext(); )
if (!cond(i.next()))
i.remove();
}
Two things should be kept in mind when looking at this simple piece of code:
  • The code is polymorphic: it works for any Collection that supports element removal, regardless of implementation. That's how easy it is to write a polymorphic algorithm under the collections framework!
  • It would have been impossible to write this using Enumeration instead of Iterator, because there's no safe way to remove an element from a collection while traversing it with an Enumeration.

 

Normal syntax

Let there be collection c.

Iterator it = c.iterator();

Example with Java 5 generics

ArrayList<String> alist = new ArrayList<String>();
// . . . Add Strings to alist

for (Iterator<String> it = alist.iterator(); it.hasNext(); ) {
String s = it.next(); // No downcasting required.
System.out.println(s);
}

Example as above but with enhanced Java 5 for loop

for (String s : alist) {
System.out.println(s);
}

Example pre Java 5, with explicit iterator and downcasting

An iterator might be used as follows, wi.
ArrayList alist = new ArrayList(); // This holds type Object.
// . . . Add Strings to alist

for (Iterator it = alist.iterator(); it.hasNext(); ) {
String s = (String)it.next(); // Downcasting is required pre Java 5.
System.out.println(s);
}
 
  • The order in which elements are visited is defined by the underlying implementation class.
  • Should the Collection change while we are iterating through it, the methods hasNext() and next() will throw the RuntimeException –ConcurrentModificationException. This does not need to be caught, but may be useful. When next() goes beyond the end of the Collection, perhaps because the hasNext() method was not used correctly, the exception NoSuchElementException is thrown. This is again a RuntimeException and so there is no need for a try…catch block.

No comments:

Post a Comment