Chapter 10.1.5 Iterators and for each Loops | Introduction to Programming Using Java

Chapter 10.1.5  Iterators and for each Loops | Introduction to Programming Using Java

10.1.5  Iterators and for each Loops

 

Chapter 10.1.5  Iterators and for each Loops | Introduction to Programming Using Java

 

The interface Collection<T> defines a few basic generic algorithms, but suppose you want to write your own generic algorithms. Suppose, for example, you want to do something as simple as printing out every item in a collection. To do this in a generic way, you need some way of going through an arbitrary collection, accessing each item in turn. We have seen how to do this for specific data structures: For an array, you can use a for loop to iterate through all the array indices.

For a linked list, you can use a while loop in which you advance a pointer along the list. For a binary tree, you can use a recursive subroutine to do an infix traversal. Collections can be represented in any of these forms and many others besides. With such a variety of traversal mechanisms, how can we even hope to come up with a single generic method that will work for collections that are stored in wildly different forms? This problem is solved by iterators.

An iterator is an object that can be used to traverse a collection. Different types of collections have iterators that are implemented in different ways, but all iterators are used in the same way. An algorithm that uses an iterator to traverse a collection is generic because the same technique can be applied to any type of collection.

Iterators can seem rather strange to someone who is encountering generic programming for the first time, but you should understand that they solve a difficult problem in an elegant way.

The interface Collection<T> defines a method that can be used to obtain an iterator for any collection. If coll is a collection, then coll.iterator() returns an iterator that can be used to traverse the collection. You should think of the iterator as a kind of generalized pointer that starts at the beginning of the collection and can move along the collection from one item to the next. Iterators are defined by a parameterized interface named Iterator<T>.

If coll implements the interface Collection<T> for some specific type T, then coll.iterator() returns an iterator of type Iterator<T>, with the same type T as its type parameter. The interface Iterator<T> defines just three methods. If iter refers to an object that implements Iterator<T>, then we have:

  • next() — returns the next item, and advances the iterator. The return value is of type T. This method lets you look at one of the items in the collection. Note that there is no way to look at an item without advancing the iterator past that item. If this method is called when no items remain, it will throw a NoSuchElementException.
  • hasNext() — returns a boolean value telling you whether there are more items to be processed. In general, you should test this before calling iter.next().
  • remove() — if you call this after calling iter.next(), it will remove the item that you just saw from the collection. Note that this method has no parameter. It removes the item that was most recently returned by iter.next(). This might produce an UnsupportedOperationException, if the collection does not support removal of items.

Using iterators, we can write code for printing all the items in any collection. Suppose, for example, that coll is of type Collection<String>. In that case, the value returned by coll.iterator() is of type Iterator<String>, and we can say:

 

78 2 Chapter 10.1.5 Iterators and for each Loops | Introduction to Programming Using Java

The same general form will work for other types of processing. For example, the following code will remove all null values from any collection of type Collection<JButton> (as long as that collection supports removal of values):

Chapter 10.1.5  Iterators and for each Loops | Introduction to Programming Using Java

(Note, by the way, that when Collection<T>, Iterator<T>, or any other parameterized type is used in actual code, they are always used with actual types such as String or JButton in place of the “formal type parameter” T. An iterator of type Iterator<String> is used to iterate through a collection of Strings; an iterator of type Iterator<JButton> is used to iterate through a collection of JButtons; and so on.)

An iterator is often used to apply the same operation to all the elements in a collection. In many cases, it’s possible to avoid the use of iterators for this purpose by using a for-each loop. The for-each loop was discussed in Subsection 3.4.4 for use with enumerated types and in Subsection 7.2.2 for use with arrays. A for-each loop can also be used to iterate through any collection. For a collection coll of type Collection<T>, a for-each loop takes the form:

Chapter 10.1.5  Iterators and for each Loops | Introduction to Programming Using Java

Here, x is the loop control variable. Each object in coll will be assigned to x in turn, and the body of the loop will be executed for each object. Since objects in coll are of type T, x is declared to be of type T. For example, if namelist is of type Collection<String>, we can print out all the names in the collection with:

 

Chapter 10.1.5  Iterators and for each Loops | Introduction to Programming Using Java

This for-each loop could, of course, be written as a while loop using an iterator, but the for-each loop is much easier to follow.

 

SEE MORE:

16 thoughts on “Chapter 10.1.5 Iterators and for each Loops | Introduction to Programming Using Java”

Leave a Comment