12.3 Iteration
We can use a clean enhanced for loop with Java's HashSet
However, if we try to do the same with our ArraySet
, we get an error. How can we enable this functionality?
Enhanced For Loop
Let's first understand what is happening when we use an enhanced for loop. We can "translate" an enhanced for loop into an ugly, manual approach.
The above code translates to:
Let’s strip away the magic so we can build our own classes that support this.
The key here is an object called an iterator.
For our example, in List.java we might define an iterator()
method that returns an iterator object.
Now, we can use that object to loop through all the entries in our list:
This code behaves identically to the foreach loop version above.
There are three key methods in our iterator approach:
First, we get a new iterator object with Iterator<Integer> seer = friends.iterator();
Next, we loop through the list with our while loop. We check that there are still items left with seer.hasNext()
, which will return true if there are unseen items remaining, and false if all items have been processed.
Last, seer.next()
does two things at once. It returns the next element of the list, and here we print it out. It also advances the iterator by one item. In this way, the iterator will only inspect each item once.
Implementing Iterators
In this section, we are going to talk about how to build a class to support iteration.
Let's start by thinking about what the compiler needs to know in order to successfully compile the following iterator example:
We can look at the static types of each object that calls a relevant method. friends
is a List, on which iterator()
is called, so we must ask:
Does the List interface have an iterator() method?
seer
is an Iterator, on which hasNext()
and next()
are called, so we must ask:
Does the Iterator interface have next/hasNext() methods?
So how do we implement these requirements?
The List interface extends the Iterable interface, inheriting the abstract iterator() method. (Actually, List extends Collection which extends Iterable, but it's easier to codethink of this way to start.)
Next, the compiler checks that Iterators have hasNext()
and next()
. The Iterator interface specifies these abstract methods explicitly:
What if someone calls next
when hasNext
returns false?
Will hasNext
always be called before next
?
Specific classes will implement their own iteration behaviors for the interface methods. Let's look at an example. (Note: if you want to build this up from the start, follow along with the live coding in the video.)
We are going to add iteration through keys to our ArraySet
class. First, we write a new class called ArraySetIterator, nested inside of ArraySet:
This ArraySetIterator implements Iterator<T>
, which means it implements a hasNext()
method, and a next()
method, using a wizPos
position as an index to keep track of its position in the array. For a different data structure, we might implement these two methods differently.
Thought Exercise: How would you design hasNext()
and next()
for a linked list?
Now that we have the appropriate methods, we could use a ArraySetIterator to iterate through an ArraySet
:
We still want to be able to support the enhanced for loop, though, to make our calls cleaner. So, we need to make ArraySet
implement the Iterable interface. The essential method of the Iterable interface is iterator()
, which returns an Iterator object for that class. All we have to do is return an instance of our ArraySetIterator
that we just wrote!
Now we can use enhanced for loops with our ArrraySet
!
Here we've seen Iterable, the interface that makes a class able to be iterated on, and requires the method iterator()
, which returns an Iterator object. And we've seen Iterator, the interface that defines the object with methods to actually do that iteration. You can think of an Iterator as a machine that you put onto an iterable that facilitates the iteration. Any iterable is the object on which the iterator is performing.
With these two components, you can make fancy for loops for your classes!
ArraySet
code with iteration support is below:
Last updated