Main Page

Previous Next

Iterators

In the LinkedList class that we developed in Chapter 6 you might have thought that the mechanism for getting the objects from the list was a little cumbersome. It was necessary to obtain the first element by using one method, getFirst(), and successive elements by another method, getNext(). This makes the first element in a list a 'special case' so processing the elements has to take account of this and is a little more complicated than perhaps it needs to be.

A much better approach that can be used to process the elements from a collection sequentially involves something called an iterator.

Note 

It is worth noting at this point that Java also provides something called an enumerator. An enumerator provides essentially the same capability as an iterator, but it is recommended in the Java documentation that you should use an iterator in preference to an enumerator for collections.

In general an iterator is an object that you can use to retrieve all the objects in a collection one by one. Someone dealing cards from a deck one by one is acting as an iterator for the card deck – without the shuffle, of course.

In Java, an iterator is an interface that can be implemented by a collection class. Any collection object can create an object of type Iterator that encapsulates references to all the objects in the original collection in some sequence, and that can be accessed using the Iterator interface methods. In other words an iterator provides an easy way to get at all the objects in a collection one at a time. The basic mechanism for using an iterator in Java is illustrated below.

Click To expand

The Iterator interface in java.util declares just three methods:

Method

Description

next()

Returns an object as type Object starting with the first, and sets the Iterator object to return the next object on the next call of this method. If there is no object to be returned the method throws a NoSuchElementException exception.

hasNext()

Returns true if there is a next object to be retrieved by a call to next().

remove()

Removes the last object returned by next() from the collection that supplied the Iterator object. If next() has not been called or if you call remove() twice after calling next(), an IllegalStateException will be thrown. Not all iterators support this method, in which case an UnsupportedOperationException exception will be thrown if you call it.

Since calling the next() method for an object that implements Iterator returns successive objects from the collection, starting with the first, you can progress through all the objects in a collection very easily with a loop such as:

MyClass item;                              // Store an object from the collection
while(iter.hasNext()) {                    // Check that there's another
  item = (MyClass)iter.next();             // Retrieve next object
  // Do something with item...
}

This assumes iter is of type Iterator and stores a reference to an object obtained from whatever collection class we were using. As we shall see shortly, objects that are collections have a method, iterator(), that returns an iterator for the current contents of the collection. The loop continues as long as the hasNext() method returns true. Since the next() method returns the object as type Object, we will usually need to cast it to its actual type. Each time you need to go through the objects in a collection you obtain another iterator, as an iterator is a 'use once' object.

Only the Java collection classes that are sets or lists make iterators available directly. However, as we will see, a map provides methods to enable the keys or objects, or indeed the key/object pairs, to be viewed as a set, so an iterator can then be obtained to iterate over the objects in the set view of the map.

The iterator we have seen here is a one-way street – we can go through the objects in a collection one at a time, and that's it. This is fine for many purposes and is a lot safer than a hand coded loop, as there's no possibility of getting the boundary conditions wrong. However, if this is not enough, and there will be times when it isn't, there's another kind of iterator that is more flexible.

List Iterators

The ListIterator interface declares methods that you can use to traverse a collection of objects backwards or forwards. You don't have to elect for a particular direction either. You can change from forwards to backwards and vice versa, so an object can be retrieved more than once.

The ListIterator interface extends the Iterator interface so the iterator methods you have seen still apply. The methods defined in the ListIterator interface that you use to traverse the list of objects are:

Method

Description

next()

Retrieves the next object in sequence – the same as for the Iterator interface.

hasNext()

Returns true if there is an object that will be returned by next().

nextIndex()

Returns the index of the object that will be returned by the next call to next(), or returns the number of elements in the list if the ListIterator object is at the end of the list.

previous()

Returns the previous object in sequence in the list. You use this method to run backwards through the list.

hasPrevious()

Returns true if the next call to previous() will return an object.

previousIndex()

Returns the index of the object that will be returned by the next call to previous(), or returns -1 if the ListIterator object is at the beginning of the list.

You can alternate between calls to next() and previous() to go backwards and forwards through the list. Calling previous() immediately after calling next() will return the same element – and vice versa.

With a ListIterator you can add and replace objects, as well as remove them from the collection. ListIterator declares the following methods for this:

Method

Description

remove()

Removes the last object that was retrieved by next() or previous(). The UnsupportedOperation exception is thrown if the remove operation is not supported for this collection, and an IllegalStateException will be thrown if next() or previous() have not yet been called for the iterator.

add(Object obj)

Adds the argument immediately before the object that would be returned by the next call to next(), and after the object that would be returned by the next call to previous(). The call to next() after the add() operation will return the object that was added. The next call to previous() will not be affected. This method throws an UnsupportedOperationException if objects cannot be added, a ClassCastException if the class of the argument prevents it from being added, and IllegalOperationException if there is some other reason why the add cannot be done.

set(Object obj)

Replaces the last object retrieved by a call to next() or previous(). If neither next() nor previous() have been called, or add() or remove() have been called most recently, an IllegalStateException will be thrown. If the set() operation is not supported for this collection an UnsupportedOperationException will be thrown. If the class of the reference passed as an argument prevents the object being stored in the collection, a ClassCastException will be thrown. If some other characteristic of the argument prevents it being stored in the collection, an IllegalArgumentException will be thrown.

Now we know about iterators we need to find out a bit about the collection classes themselves in order to make use of them.

Previous Next
JavaScript Editor Java Tutorials Free JavaScript Editor