An Iterator
is an object that can be attached to any type of Collection
object. Since an ArrayList
is a type of Collection
, you can use an Iterator
to traverse an ArrayList from first to last element. Doing so is easier and safer than using a classic for-loop because an Iterator
keeps track of where it is in the list even if we are adding and removing from it.
Consider the code below:
ArrayList <String> names = new ArrayList <String>();
names.add("George");
names.add("Nancy");
names.add("John");
names.add("John");
names.add("Bill");
names.add("Maria");
// Remove anyone named "John"
for (int i = 0; i < names.size(); i++)
if (names.get(i).equals("John"))
names.remove(i);
// Print the revised list
for (int i = 0; i < names.size(); i++)
System.out.println(names.get(i));
There is a problem with this code. Can you identify the problem? Spend a few minutes thinking about the problem and come up with a way to fix it using the same loop structure and code as given above. The required bug fix is small but critical.
See Answer Below 1
A much more elegant solution is available using Iterators
. Since Iterator
objects keep track of the items in a Collection
for you, you do not need to worry about the index counter skipping past items. In fact, you do not even need an index counter! Read the API (java.util.Iterator)
and then study the code below. It does the same thing as the code shown above but uses an Iterator
to traverse the list of names:
Iterator<String> iter = names.iterator();
// Remove anyone named "John"
while(iter.hasNext())
if (iter.next().equals("John"))
iter.remove();
Iterators
are invaluable when using advanced Data Structures (see the AB curriculum). Even so, you should consider using them in your code from now on because they are are a clean way run through an ArrayList
or other type of Collection
even when the contents of the Collection
change.
As long as you don't need to modify the contents of a Collection, there is a new and simpler type of loop structure that came with the release of Java 5. The AP Exam uses it extensively and you will therefore need to know it and use it.
It's called a For-Each loop and here's the syntax:
Collection b;
for (Object a : b)
a.whatever();
The loop reads as follows: "for each Object a in b ... do a.whatever()". This simplifies your code greatly as you do not need a loop counter. The for-each loop automatically steps through your Collection of objects and returns the next object for you to use at will.
Here is an example using classic for loops.
// suits is an ArrayList of Suit objects
// faces is an ArrayList of Face objects
// cards is an ArrayList of Card objects
for(int i = 0; i < faces.size(); i++)
for(int j = 0; i < suits.size(); j++)
cards.add(new Card(faces.get(i), suits.get(j)));
And here is the for-each version. Much better!
for(Face f: faces)
for(Suit s: suits)
cards.add(new Card(f, s));
The code reads smoothly:
for each Face object in faces, do...
for each Suit object in suits, do...
For more examples, search the Web for "Java for-each loop".
Know it, use it, love it. The for-each loop!
When the first occurance of "John" is found it is deleted from the ArrayList. No problem there. However, the loop counter should not be incremented when an item is deleted because doing effectively skips over the next item. Trace this code by hand and you'll see it happen before your eyes. You will find that the second instance of "John" is never checked because the loop counter skips right past it.
To fix this, you need to prevent the counter from incrementing when an item is deleted:
if (names.get(i).equals("John"))
names.remove(i--); // Decrementing keeps the counter where it belongs
go back ↩
Last modified: November 14, 2023
Back to The Wrapper Classes