95.105 - Introduction to Programming
Fall 2001

 7  Vectors, Enumerations and StringTokenizers


What's in This Set of Notes ?


 7.1 Vectors and ArrayLists


Arrays have a fixed size...they cannot grow or shrink in response to an application's changing storage requirements.  Java has a class called Vector for just this purpose.   In more recent versions of Java (i.e., Java2) there is another class called ArrayList that has the same functionality as the Vector class.

A Vector (or ArrayList):

To make a new vector we just say something like this:
 
Vector myVector = new Vector();                     //initial capacity size 10
Vector myVector = new Vector(int cap);             //initial capacity size cap
Vector myVector = new Vector(Collection col);       //make a new Vector initially with the elements 
                                                    //being the same as those in the given collection, 
                                                    //which may be another Vector

Note that the ArrayList has similar constructors:
 
ArrayList myList = new ArrayList();
ArrayList myList = new ArrayList(int cap);
ArrayList myList = new ArrayList(Collection col);

Here are some of the standard Vector methods.   Note that the ArrayList uses the same methods as the Vector.   Previous versions of java used different methods for the Vector class.   You should use the most recent versions shown here.
 
Return Value
Method (version >= 1.2)
Description
void add(Object obj) Place the given object at the end of the Vector.  If there is no room, it grows by its increment.
void add(int pos, Object obj) Insert the given object at the given position in the Vector.  All other elements are shifted upward to have an index one greater that they had previously.
boolean addAll(Collection col) Adds all the elements of the given collection (which may be another Vector) to the receiver Vector.  Returns true if the receiver Vector changed as a result of this call.
Object get(int pos) Return the element at the given position in the Vector.
void set(int pos, Object obj) Replace the element at the given position with the given object. 
boolean remove(Object obj) Remove the first occurence of the given object from the vector.  It returns true if it found the object, otherwise false.  All elements after it are shifted toward the beginning of the vector.
Object remove(int pos) Remove the element at the given position in the vector.  The newer version returns the object that was removed, the older version returns void.
boolean removeAll(Collection col) Removes from the receiver vector all elements that are in the given collection.   Return true if the receiver changed.
boolean retainAll(Collection col) Removes from the receiver vector all elements that are NOT  in the given collection.   Return true if the receiver changed.
void clear() Remove all the elements from the vector.
boolean isEmpty() Return whether or not there are any elements in the vector.
boolean contains(Object obj) Return whether or not the vector contains the given object.  The object method equals() is used to determine this.
boolean containsAll(Collection col) Return whether or not the vector contains all the objects that are within the given collection.  The object method equals() is used to determine this.
int indexOf(Object obj) Return the position of the first occurrence of the given object.  -1 is returned if the object is not there.
int size() Return the number of elements in the vector.
int capacity() Return the current capacity of the vector.
Enumeration elements() Return an enumeration containing the elements of the vector.   This does not work for ArrayLists, only Vectors.
Iterator iterator() Return an iterator containing the elements of the vector.

Note that the get() method has a return type of Object.   That means whenever you extract an object from a Vector, you must then type cast it to the kind of object that you want.  In general, a Vector may contain multiple types of objects, so a Vector must supply methods that support the extraction of any types of objects as well.   Now since a method can only have one return type, Java would need to make a special method for each kind of object that may be possibly stored in a Vector.  Clearly this is impossible and so Java decided to have a return type of Object, since all objects are subclasses of Object anyway.   So, upon getting an element out of the Vector, we must type cast it back into its original type (or as we'll see later to a super type or interface) so that we can use the object again.

Here is how to use a Vector to store some integers, perhaps peoples ages.   Note that we must use the Integer wrapper class:

Vector v = new Vector();
v.add(new Integer(4));
v.add(new Integer(23));
v.add(new Integer(76));
v.add(new Integer(34));
v.add(new Integer(28));

//System.out.println(v.contains(76)); //This won't compile
System.out.println(v.contains(new Integer(76)));

double sum = 0;
for (int i=0; i<v.size();i++) {
    int value = ((Integer)v.get(i)).intValue();
    sum += value;
}
System.out.println(sum/v.size());

Notice that we had to type-cast the object coming out of the vector.   Also, we used intValue() to unwrap the Integer so that we could use it as a data type in a calculation.   As we can see, it is a little tedious to have to wrap up the data types like this, but that's the way it MUST be done.

Lets take a look at another example that stores Pet objects (assume that Pets have names).  This time we'll use ArrayLists:

ArrayList v = new ArrayList();
String[]  names = {"Al", "Zack", "Sally", "Mel", "Fry", "Jorg", "Jake", "Sven", "Ren", "Stimpy", "Jim", "Orson", "Ash" };
for (int i=0; i<names.length;i++) {
    Pet p = new Pet();
    p.setName(names[i]);
    v.add(p);
}
Now if we wanted to get those pets back out and print out their names, we must use type-casting again:
for (int i=0; i<v.size();i++) {
    Pet p = (Pet)v.get(i);
    System.out.println(p.getName());
}
Notice that the ArrayLists are used the same as the Vector class.
 


 7.2 Enumerations and Iterators


The elements() method of the Vector class returns something called an Enumeration.  An Enumeration is an object that allows a program to "walk through" a set of elements one at a time.  Enumerations are not supported by ArrayLists, instead, ArrayLists use iterators, which are also supported by Vectors.   Enumerations are widely used in Java.   Many, many methods that need to return collections of objects, often do so by returning the elements as an Enumeration.   Even though Enumerations are "old news", we still discuss them here because there are still many java enterprise methods that return Enumerations...and we want to know how to use them.

There are two useful methods defined by the Enumeration interface:

Example

Here is an example of how to use the Enumeration class on a Vector:

Here is the output:
 
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

Enumerations do have problems though.  If for example we want to enumerate through some items in a vector and remove items as well from the vector, then this does not work properly.  For some reason, Java does not allow you to remove from a collection that you are enumerating through !!   Consider this (logically correct) example, and then look at the output to follow:


Here is the output:
 
Before Vector: [one, two, three, four, five, six, seven, eight, nine, ten]
one
two
three
five
six
seven
nine
ten
After Vector: [one, two, four, five, six, eight, nine, ten]

Notice that the Enumeration did not produce all the items.  Also, the vector after removing is not correct  since the "eight" string was NOT removed as it should have been.    This is a problem with Enumerations.

The moral is...don't use Enunerations if you are gonna be removing from the collection that you are enumerating through!

Instead, use an Iterator.  An interator is a tool for iterating (i.e., traversing) through the elements of a collection.   To get an iterator, send the iterator() message to a collection (such as a Vector):

    aVector.iterator();

An iterator works a lot like an enumeration and has the following methods available:
 
boolean hasNext() returns whether or not there is another element in the collection
Object next() returns the next element in the collection
void remove() removes the item from the collection that was just obtained from a call to next().  Note that you don't specify here the item to be removed.   Also, note that the item is actually removed from the collection!

Here is how to use the iterator in a similar example to that above:


Here is the resulting output:
 
Before Vector: [one, two, three, four, five, six, seven, eight, nine, ten]
one
two
three
four
five
six
seven
eight
nine
ten
After Vector: [one, two, four, five, six, nine, ten]

Notice that we are now saying remove() to the iterator, NOT to the Vector.  This is important.   The iterator essentially keeps itself coordinated with the collection that it is iterating through so that no elements are lost along the way.


 7.3 The Car and Autoshow Example


Example

Consider an Autoshow that contains various Cars from various companies.  Customers go to the autoshow with dreams of someday owning cars such as these and/or to investigate the cars/trucks/minivans that are accessable in their price range.  We will pick four characteristics of the cars that are interesting.  Obviously when buying a car, there are many other options and these can easily be added.   For each car, we will keep the name, make, color and topSpeed.  The first step in making the object is to define the Car class and create its get and set methods, its constructor and a toString() method.

Of course, we'll at least test the constructor and the toString() method: Here is the output from the test:
 
Here are some cars:
(Red Porsche 959)
(Red Pontiac GrandAm GT)
(White Ford Mustang)
(Blue Volkswagon Rabbit)
(Silver Volkswagon Jetta)

An Autoshow should maintain a vector of Car objects.  Again, we'll make appropriate get, constructor and toString methods.   Note that the constructor will set the cars to be a new vector.  We do not ever need to set the cars instance variable since it will always be this vector.  We will merely add to the vector when cars arrive at the autoshow.  Note that we must import the Vector class from the utilities package.  We'll also import the Enumeration class as we will need this later.

Now in order to add cars to the autoshow, we need an addCar(Car aCar) method.  We'll also add a method that will return the number of cars in the autoshow. Let's now make some interesting methods.  We'll start by making a method that returns all the cars with a given make.  We'll make a new vector, go through all cars, check their make, and if the make matches the one we're looking for we'll add that car to the nex vector.  Here is the pseudocode. To do the loop, we'll make use of the Enumeration class. Now lets make a method that returns all of the different makes of cars at the autoshow.  Of course, we want only a list of the different makes, so no duplicates are allowed.  Here is the pseudocode. Once again, to do the loop, we'll make use of the Enumeration class. Now what about finding the fastest car ?  This is the car with the maximal top Speed.  here is the pseudocode: Now here is the actual code: Now a harder one.  Lets find the most common color of all cars at the autoshow.  Once again, start with pseudocode: And now, the final code.  This time, we'll use nested for loops: Now , you thought that was tough...now we're gonna get a real toughie.  Write a method that prints out all the cars in order of their top speed (fastest cars first).  Cars with the same speed will appear in arbitrary order amongst themselves.  We'd better start with pseudocode.  We'll first get a copy of all cars so that we do not destroy the original Vector.  To sort them, we'll take the simple approach of repeatedly finding the minimum. Now it's easy to write the code: Write a method that prints out all the cars in alphabetical order of their make.  Cars with the same make will appear in arbitrary order amongst themselves.  We can easily see that this is very similar to the previous method, so we don't need to write pseudocode. We've written quite a few methods.  Lets test them out with a nice test case:
  Here are the test results:
 
Autoshow with 15 cars
Here are the Pontiac cars:
[(White Pontiac Grand-Am), (Black Pontiac Firebird)]
Here are the Ford cars:
[(White Ford Mustang), (Yellow Ford Escort)]
Here are the different makes:
[Porsche, Pontiac, Ford, Volkswagon, Geo, Toyota, Honda, Nissan, BMW, Mazda]
This is the fastest car:
(Gold BMW 525)
The most common color is White

Here are the cars sorted by top speed:
(Gold BMW 525)
(red Porsche 959)
(White Ford Mustang)
(Red Mazda RX7)
(Black Toyota MR2)
(Silver Nissan Altima)
(Black Honda Civic)
(Green Mazda MX6)
(White Pontiac Grand-Am)
(Yellow Geo Storm)
(Black Pontiac Firebird)
(Silver Volkswagon Jetta)
(Blue Volkswagon Rabbit)
(White Honda Prelude)
(Yellow Ford Escort)

Here are the cars sorted by make:
(Gold BMW 525)
(White Ford Mustang)
(Yellow Ford Escort)
(Yellow Geo Storm)
(Black Honda Civic)
(White Honda Prelude)
(Red Mazda RX7)
(Green Mazda MX6)
(Silver Nissan Altima)
(White Pontiac Grand-Am)
(Black Pontiac Firebird)
(red Porsche 959)
(Black Toyota MR2)
(Blue Volkswagon Rabbit)
(Silver Volkswagon Jetta)


 


 7.4 String Tokenizer


The StringTokenizer class allows us to break a string into individual substrings based on some separation criteria.  For example, we can extract the words from a sentence one at a time.   The term delimeter is used to indicate the character(s) that separate the "words" (also known as tokens).

We ca create a StringTokenizer as follows:
 
StringTokenizer tokens = new StringTokenizer(String aString);

The default deliminators are " \n\t\r".  That is, the string tokens are separated by spaces, newlines, tabs and carriage returns.   It is used similar to Enumerations.  Here are the useful methods:
 
Return Value
Method
Description
int countTokens() Returns the number of tokens of the String to be tokenized.
boolean hasMoreTokens() Returns whether or not there are more tokens in the String being tokenized.
String nextToken() Return the next token in the String being tokenized.

Example

Here is a big example that tests many of the String methods:

Here is the output:
 
The String has 5 words.
Here are the words, one by one:
Half
of
12
is
six

Use a StringTokenizer whenever you find that you need to break apart a String into pieces.