Java has an entire framework dedicated to collections. The Collections interface provides useful utilities for managing lists of items.
Think of a collection as an array that can vary in size (an array is always a fixed size).
A collection is always a group of class-level objects. This means, for example, that you can have a collection Integer, but cannot have a collection of int (a primitive data type).
A collection does not have to be all the same object. You can place any combination of class-level objects into a collection. This is not advisable, however, because class-level objects are stored as Object - it is necessary to cast it to the correct type when retrieved from the collection. It makes more sense to always store the same class type, so the object does not need to be tested for its' type (using the instanceof operator).
The majority of Java programming still utilizes two common legacy classes: Vector and Hashtable.
Vector
Vector is a simple collection of objects. The most common methods used are:
add(Object o) - adds an element to the Vector
size() - returns an int representing the number of elements in the Vector.
elementAt(int index) - returns the Object at the specified position in the Vector. The Object will need to be cast to the appropriate type.
elements() - returns an Enumeration of the components in the Vector.
There are two ways to iterate through the list of items in a Vector:
- Use the size() and elementAt() in a for loop:
Address a = null;
int s = vector.size();
for (int i=0; i<s; i++) {
a = (Address)v.elementAt(i);
// other code as needed
}
Note that the size is assigned to a variable. This is done for two reasons. First, it saves the overhead of repeatedly calling the size() method. Second, if the size of the Vector changes for any reason while inside the for loop, it will affect the iteration of the loop.
- Use the Enumeration:
Address a = null;
Enumeration e = v.elements();
while ( e.hasMoreElements() ) {
a = (Address)e.nextElement();
// other code as needed
}
An enumeration is a one-way, one-time trip through the list.Hashtable
A Hashtable is similar to a Vector, except objects are stored and retrieved using a key value.
In my FileLoader program, a Record is a collection of Field classes.
A Field class defines the name, value, size, start position, and end position. Size, start, and end are used for parsing the value from the fixed input line of the data file.
A Record contains a Hashtable of field values. A fixed input line is read in and parsed. A separate Field object is created for each Field in the descriptor file. The field value is parsed from the input line and is appended to the Hashtable using it's name as the key. The method used to add to a Hashtable is:
put(Object key, Object value)
The front end to the FileLoader program then has to iterate through the list. But, we want to retrieve the fields by name from the list. So, we use the keys() method of Hashtable, which returns an Enumeration of the keys. In the while loop over the Enumeration (hasMoreElements()), we use the nextElement() method to get the next key value, then pass that to the get() method of Hashtable to return the field value.
The Client-Side Setup
- Modification of the Front End (AddressFrontEnd.java)
First, we need to set the SecurityManager, just as we did for the Server.
Next, we create an instance of the interface class. Use the lookup() method of the Naming class, and cast the returning Object to the appropriate type. The lookup() method takes a String as an argument - the String uses "rmi" as the protocol, passes the name of the server and the name we used in the implementation class with the Naming.rebind() method.
Loading the Choice - we call the getList() method from the interface instance, then iterate through the Vector returned.
The itemStateChanged() event - we call the getAddress() method of the interface, passing it the AddressID selected in the Choice. We get an Address bean back, which we use to populate the TextFields.
The actionPerformed() event - "add" and "update" create and populate an Address bean, and pass it to the appropriate method of the interface instance. For "delete" we call the deleteAddress() method of the interface instance, passing it the AddressID from the Label.
- Required Supporting Classes
The front end will also need the bean, the implementation stub, and the interface classes, as well as the policy file.The Client-Side Startup
- Open a DOS window and change to the directory containing your class files.
- Start your client class, but tell it where the security policy is: java -Djava.security.policy=wideopen.policy AddressFrontEnd