CS 3340 OOP
Exercise 6: Stack: ArrayList, HashMap
Chapter Readings: TIJ [11]

Goal:To learn more advanced techniques for container classes, and to learn generics, a compile-time check of object type.


Tutorial

Two very useful containers (collections of objects) are: API: ArrayList and API: HashMap

The ArrayList is similar to a Vector in that it can be treated as an array (in the sense indexing) or as a list (in the sense of insert/delete). HashMap is an implementation of a hash table, from a Data Structures course, that is, an object can be stored based on a key. Later, the object can be retrieved with the same key. You might recall the two implementations to take care of collisions (hash function returns the same index for different keys): probe for an empty spot in the table or maintain a linked list of the collisions. But it really doesn't matter: the HashMap class hides these details, we just care about put() and get() of our objects.

Recall the Person class from Ex1: Person.java

and the testing program from Ex5 on Vectors: VectorTest.java

Here is the equivalent program using an ArrayList: ArrayListTest.java

They are much the same with 3 main differences:

Here is a Generics Introduction and more details in a Generics Tutorial

As a reminder:

private Vector<Person> stack = new Vector<Person>(); // if homogeneous, only Persons
private Vector<Object> stack = new Vector<Object>(); // if heterogeneous, any Object

The above is tested with a demo


Assignment

Copy Stack.java using Vector from Ex5: cp ../ex5/Stack.java .

Modify the code by replacing the Vector with an ArrayList. The ArrayListTest.java and API: ArrayList should help with the necessary method calls. Also, your ArrayList should use generics of <Person>. Because this is specifically for type Persons, push()/pop() can be either Person or Object. Your choice.

After that works, declare a HashMap in Stack.java, along with generics of <Person>. But note that API: HashMap has two fields: HashMap<K, V> where K is the type of Object that will be used as the key, and V is the type of value to be stored with the key. In our case: K=String (but it could be other Objects in other applications) and V=Person.

Now modify Stack.java to always put() into the HashMap for every push() and to remove() on every pop(). That is, besides maintaining a LIFO list (ArrayList), the Stack is also providing a direct indexing mechanism via HashMap. Although this is unusual for a Stack, it does illustrate the power of built-in classes like ArrayList and HashMap. And for a Person, what do you think the key would be?

Add two methods to your Stack class:

public Iterator arrayIterator()
public Iterator hashIterator()

There are two data structures inside your Stack data structure: array list and a hash table. It is possible to request from these structures that they give you an Iterator. That is what the above methods should do. It is easy for an array list. Look at API: HashMap again. Hint: get a Collection, and then get an Iterator.

Now make a testing main(). Here is what the output should look like:

Iteration of the Stack's Array
Name 1  10
Name 2  20
Name 3  30
Iteration of the Stack's Hash
Name 2  20
Name 1  10
Name 3  30
Pop the Stack
Name 3  30
Name 2  20
Name 1  10
This means push three Persons, use the array iterator to print, use the hash iterator to print, and then pop() (and print) as usual. Look closely at the above: the Array looks as expected, but the Hash seems to be out-of-order. That's OK. Hash Tables use a hash function that does not put them in order sequentially. And then the pop() is LIFO as expected.

Turn-In: Stack.java, including a commented-out listing of the resultant output.