In the discussion
of Vector
we mentioned the Enumeration
class, which provides for stepping through the elements of a list
such as a Vector.
However, Iterator,
introduced with Java 1.2, is now preferred to Enumeration.
Iterator
differs from Enumeration
in 2 ways:
- Elements can be safely removed from Vector
using the remove
(int index) without causing the Iterator
to fail..
- The hasMore
() and next
() methods in Iterator
are short and direct as opposed to the corresponding long and
boring methods nextElement
() and hasMoreElements
() in Enumeration.
All the old container classes were retro-fitted with the Java 1.2
release to support the Iterator
interface and the new container classes added in JDK 1.2 with the
Collections Framework support only
the Iterator
interface.
The syntax for iterating over the elements in a Vector is as follows
Vector
vec = new Vector;
// Populate it... Then later, iterate over its elements
Iterator it = vec.iterator ();
while (it.hasNext ()) {
Object o = it.next ();
}
We use an java.lang.Object
reference for the retrieved element but could cast it to a specific
type if we knew what type of object is in the list.
The following snippet illustrates another popular iteration style,
this time using an ArrayList,
which is preferred over Vector
in a thread-safe situation:
ArrayList
a_list = new ArrayList ();
...
for (Iterator it = a_list.iterator (); it.hasNext ();
) {
Object o = it.next ();
}
Again, we retrieve Object
types from the Iterator.
All these container objects, Vector,
ArrayList,
and all the others, accept input of any kind of object. They can
do this because the add()
method receives Object
as the parameter type, and since Object
is the superclass of all other object types, any kind of object
can be added.
The containers, however, don't know what kinds of objects are being
stored in them (see, however, the generics
feature of J2SE in the next section).
Therefore, when retrieving an object from one of the containers,
it can only be returned as a Object
type. In most cases, you need to cast the retrieved Object
to the specific object type you desire. You should know what kind
of objects you store into a container, so you can do the cast correctly.
If, however, you cast a returned Object
to a type that it does not represent (say, you cast an Integer
to a String),
the program will fail due to a runtime ClassCastException.
The next snippet illustrates the ability of the Iterator
to remove elements. First we make a list of integers from 0 to 19
and then remove all the odd integers.
//
Build an ArrayList and populate it with integers from 0 to 19.
ArrayList al = new ArrayList ();
for (int i=0; i < 20; i++) al.add (i);
// Iterate through the ArrayList, removing all the odd
integers.
int count = 0;
for (Iterator it = al.iterator (); it.hasNext (); )
{
count++;
it.next ();
if (count%2 == 0) it.remove ();
}
//
Print out the remaining elements with another Iterator.
for (Iterator it = al.iterator (); it.hasNext (); )
{
System.out.println ("element is " + it.next
());
}
The first loop simply loads the integers from 0 to 19 into the
ArrayList.
The next loop uses an iterator to retrieve each element and remove
the ones when count%2
is zero. The final loop uses another iterator to print out the contents
of the modified list. Note that we used the Iterator.remove()
method, not ArrayList.remove().
Attempting to remove an element directly from the ArrayList
generates a runtime ConcurrentModificationException.
Note also that we used the autoboxing feature (see Chapter
3) to add primitive int
types in the first loop (autoboxed to Integer
type) without having to explicitly convert them to integer wrapper
types.
References and Web Resources
Latest update: Nov. 18, 2004
|