|
![]() |
![]() |
![]() |
![]() |
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.
The Iterator interface in java.util declares just three methods:
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.
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:
Now we know about iterators we need to find out a bit about the collection classes themselves in order to make use of them.
![]() |
![]() |
![]() |