Java 5 Style Collections: Generics


Java 1.4.2 Style Collections

Java collections frameworks leading up to and including Java 1.4.2 allowed you to manage collections of objects without specifying what type of objects actually were contained in the collection. This led to the need to cast retrieved objects to the desired type if a method you wanted to call on the object was not one that overrode one of the methods defined by the Object class. This section presents several sample programs that illustrate typical collections framework programming style in Java platform versions prior to Java 5.

Creating A Set From A List

The first example program will illustrate how one type of collection can be created from another. Specifically, a List collection is created and populated with duplicate elements. Next, a Set collection is created using the elements contained in the List. However, since a Set does not allow duplicate elements, only the unique elements of the List will appear in the Set. The program is named SetTestApp and is given in example 17.5.

Example 17.5: SetTestApp.java

image from book
 1     import java.util.*; 2 3     public class SetTestApp { 4       public static void main(String[] args){ 5         List list = new LinkedList(); 6 7         for(int i=0; i<100; i++){ 8           list.add(new Integer(i%10)); 9         } 10 11        System.out.print("List Contents: "); 12        for(Iterator i = list.iterator(); i.hasNext();){ 13          System.out.print(i.next().toString()); 14        } 15        System.out.println(); 16 17        Set set = new TreeSet(list); 18        System.out.print("Set Contents: "); 19        for(Iterator i = set.iterator(); i.hasNext();){ 20          System.out.print(i.next().toString()); 21        } 22        System.out.println(); 23 24      } // end main() 25    } // end SetTestApp class definition
image from book

Referring to example 17-5 — a LinkedList collection object is created on line 5. The for loop beginning on line 7 populates the collection with 100 Integer objects. On line 8 the modulus operator is applied to the for loop’s counter variable i to yield 10 repeating sequences of Integer values 0 through 9.

After the LinkedList collection is populated its elements are printed to the screen. The for loop beginning on line 12 uses an Iterator to step through each LinkedList element. The Iterator.next() method returns the next Object in the list, and, since the Integer class has an overriding toString() method, no casting is required to call this method on the retrieved object.

On line 17 a TreeSet collection object is created using the list reference as an argument to its constructor. Since a Set cannot contain duplicate values, only the unique values contained in the LinkedList will be used to populate the TreeSet collection.

The results of running this program are shown in figure 17-17.

image from book
Figure 17-17: Results of Running Example 17.5

PeopleManager Revisited

The next example revisits the PeopleManager example originally given in chapter 9. In the original version of the PeopleManager class Person objects were stored in an array. In this version of the PeopleManager class the array has been replaced with a LinkedList. I have also added a toString() method to the Person class. The code for the complete program is given in example 17.6 through 17.8.

Example 17.6: Person.java

image from book
 1     import java.util.*; 2 3     public class Person { 4       private String first_name = null; 5       private String middle_name = null; 6       private String last_name = null; 7       private Calendar birthday = null; 8       private String gender = null; 9 10      public static final String MALE = "Male"; 11      public static final String FEMALE = "Female"; 12 13      public Person(String f_name, String m_name, String l_name, int dob_year, 14                    int dob_month, int dob_day, String gender){ 15        first_name = f_name; 16        middle_name = m_name; 17        last_name = l_name; 18        this.gender = gender; 19        birthday = Calendar.getInstance(); 20        birthday.set(dob_year, dob_month, dob_day); 21      } 22 23      public int getAge(){ 24        Calendar today = Calendar.getInstance(); 25        int now = today.get(Calendar.YEAR); 26        int then = birthday.get(Calendar.YEAR); 27        return (now - then); 28      } 29 30      public String getFullName(){ return (first_name + " " + middle_name + " " + last_name); } 31 32      public String getFirstName(){ return first_name; } 33      public void setFirstName(String f_name) { first_name = f_name; } 34 35      public String getMiddleName(){ return middle_name; } 36      public void setMiddleName(String m_name){ middle_name = m_name; } 37 38      public String getLastName(){ return last_name; } 39      public void setLastName(String l_name){ last_name = l_name; } 40 41      public String getNameAndAge(){ return (getFullName() + " " + getAge()); } 42 43      public String getGender(){ return gender; } 44 45      public void setBirthday(int year, int month, int day){ birthday.set(year, month, day); } 46 47      public String toString(){ 48        return getFullName() + " " + getGender() + " " + getAge(); 49      } 50 51     } //end Person class
image from book

Example 17.7: PeopleManager.java

image from book
 1     import java.util.*; 2 3     public class PeopleManager { 4       List people_list = null; 5 6       public PeopleManager(){ 7           people_list = new LinkedList(); 8       } 9 10      public void addPerson(String f_name, String m_name, String l_name, int dob_year, 11                            int dob_month, int dob_day, String gender){ 12          people_list.add(new Person(f_name, m_name, l_name, dob_year, dob_month, dob_day, gender)); 13      } 14 15      public void deletePersonAtIndex(int index){ 16         people_list.remove(index); 17      } 18 19      public void insertPersonAtIndex(int index, String f_name, String m_name, String l_name, 20                               int dob_year, int dob_month, int dob_day, String gender){ 21       people_list.add(index, new Person(f_name, m_name, l_name, dob_year, dob_month, dob_day, gender)); 22      } 23 24      public void listPeople(){ 25        for(Iterator i = people_list.iterator(); i.hasNext();){ 26          System.out.println(i.next().toString()); 27        } 28      } 29   }// end PeopleManager class
image from book

Example 17.8: PeopleManagerApplication.java

image from book
 1     public class PeopleManagerApplication { 2       public static void main(String[] args){ 3        PeopleManager pm = new PeopleManager(); 4 5        pm.addPerson("Steven", "Jay","Jones", 1950, 8, 30, Person.MALE); 6        pm.addPerson("Jeanie", "Sue", "Freeman", 1960, 10, 10, Person.FEMALE); 7        pm.addPerson("Richard", "Warren", "Miller", 1970, 2, 29, Person.MALE); 8 9        pm.listPeople(); 10 11       pm.deletePersonAtIndex(1); 12       pm.insertPersonAtIndex(1, "Coralie", "Sylvia", "Miller", 1962, 8, 3, Person.FEMALE); 13 14       System.out.println(); 15       pm.listPeople(); 16 17       } // end main 18     }// end PeopleManagerApplication class
image from book

Referring to example 17.7 — in the PeopleManager class the array has been replaced with a LinkedList. Also, since a LinkedList has no initial capacity setting, the constructor used to set the size of the array was removed because it was unnecessary. If you compare this version of PeopleManager to the original you will also find that I have removed the assertions as well. Because of the toString() method being added to the Person class there is no need to cast the retrieved objects in the body of the listPeople() method.

Referring to example 17.8 — the PeopleManagerApplication class adds three Person objects to the PeopleManager class. It then calls the listPeople() method on line 9. It then deletes the Person object at element 1, adds a new Person in that element location, and then calls listPeople() one last time. The results of running this program are shown in figure 17-18.

image from book
Figure 17-18: Results of Running Example 17.8

Casting Retrieved Objects

So far, in each of the previous examples casting retrieved objects to their proper type was not required because the only methods called on the retrieved objects were those defined by the Object class (i.e. toString()) and overridden in the derived classes Integer and Person. In the next example the Person class is again used to illustrate how a retrieved object must be cast to the required type to call a method unique to that type. In this example I will store a few Person objects directly into a LinkedList.

Referring to example 17.9 — a LinkedList is created on line 5 and five Person objects are added to the collection. The for loop beginning on line 13 uses an Iterator to step through the collection. Since the Person.getFulName() method is unique to the Person class, the objects retrieved from the collection must be cast to the Person type before the getFullName() method can be successfully called. Figure 17-19 shows the results of running this program.

Example 17.9: PeopleListApp.java

image from book
 1     import java.util.*; 2 3     public class PeopleListApp { 4       public static void main(String[] args){ 5         List list = new LinkedList(); 6 7         list.add(new Person("Steven", "Jay","Jones", 1950, 8, 30, Person.MALE)); 8         list.add(new Person("Rick", "W","Miller", 1963, 9, 22, Person.MALE)); 9         list.add(new Person("Lori", "Lee","Smith", 1986, 1, 19, Person.MALE)); 10        list.add(new Person("Jay", "Stirling","Johnson", 1947, 2, 02, Person.MALE)); 11        list.add(new Person("Ariel", "Beau","Green", 1990, 3, 07, Person.MALE)); 12 13        for(Iterator i = list.iterator(); i.hasNext();){ 14          System.out.println(((Person)i.next()).getFullName()); 15        } 16      }// end main() 17    } // end PeopleListApp class definition
image from book

image from book
Figure 17-19: Results of Running Example 17.9

Creating New Data Structures From Existing Collections

Although the Java collections framework contains a wide variety of general purpose collection classes you will sometimes encounter a need for a data structure that does not exist in the collection. One example of this is the need for a queue. Since the Java 1.4.2 collections framework does not provide a Queue class one can be created based upon the functionality provided by the existing LinkedList class. The following example presents a class named ActiveQueue which is based on a LinkedList. ActiveQueue is a first-in-first-out (FIFO) queue that notifies interested listeners of queue insertion events. These interested listeners can then retrieve the longest waiting element. There are three parts to this example: ActiveQueue, QueueListenerInterface, and QTesterApp. These three classes are presented in examples 17.10 through 17.12.

Example 17.10: ActiveQueue.java

image from book
 1     /**************************************************************** 2       ActiveQueue class implements a thread-safe FIFO queue 3     utilizing the java.util.LinkedList class. 4     ****************************************************************/ 5 6     import java.util.*; 7 8 9     /**************************************************************** 10      ActiveQueue classs 11      @author Rick Miller 12    ****************************************************************/ 13 14    public class ActiveQueue { 15 16         private LinkedList _list = null; 17         private Vector     _listeners = null; 18 19         /**************************************************************** 20           Default constructor 21         ****************************************************************/ 22         public ActiveQueue(){ 23            _list = new LinkedList(); 24            _listeners = new Vector(); 25         } 26 27 28         /****************************************************************** 29           get() - returns the object that's been waiting the longest. 30         ******************************************************************/ 31         public synchronized Object get(){ 32           return _list.getLast(); 33         } 34 35          /**************************************************************** 36           put() - inserts an object into the queue. 37          ****************************************************************/ 38          public synchronized void put(Object o){ 39              _list.addFirst(o); 40              this.fireQueueInsertionEvent(); 41          } 42 43          /********************************************************************* 44            removeLast() - private method that removes the last element. 45          **********************************************************************/ 46 47          private void removeLast(){ 48            _list.removeLast(); 49          } 50 51          /**************************************************************** 52             addQueueListener(QueueListenerInterface listener) adds the 53             argument QueueListener object to the _listeners Vector. 54          ****************************************************************/ 55          public void addQueueListener(QueueListenerInterface listener){ 56            _listeners.add(listener); 57          } 58 59          /**************************************************************** 60             fireQueueIntertionEvent() is a protected method called in 61             the body of the put() method to notify interested object 62             that something has been inserted into the Queue. 63           ****************************************************************/ 64          protected synchronized void fireQueueInsertionEvent(){ 65            Vector v = (Vector) _listeners.clone(); 66            for(Iterator i = v.iterator(); i.hasNext();){ 67                ((QueueListenerInterface)i.next()).queueInsertionPerformed(); 68            } 69            this.removeLast(); 70          } 71        } // end ActiveQueue class definition
image from book

Example 17.11: QueueListenerInterface.java

image from book
 1     /**************************************************************** 2       QueueListenerInterface - implemented by objects interested in 3       getting notificaiton when objects have been inserted into an 4       ActiveQueue object. 5      ****************************************************************/ 6      interface QueueListenerInterface { 7         void queueInsertionPerformed(); 8      }
image from book

Example 17.12: QTesterApp.java

image from book
 1     public class QTesterApp extends Thread implements QueueListenerInterface { 2 3       private static ActiveQueue _q = null; 4 5       static { 6         _q = new ActiveQueue(); 7       } 8 9       public QTesterApp(){ 10        _q.addQueueListener(this); 11      } 12 13      public void queueInsertionPerformed(){ 14        System.out.print("New object is in the queue!: "); 15        System.out.println(_q.get().toString()); 16      } 17 18      private void insertStuff(){ 19         for(int i = 0; i < 6; i++){ 20           _q.put(new Integer(i)); 21           try{ 22             this.sleep(10); 23           }catch(InterruptedException ignored){ } 24         } 25       } 26 27       public void run(){ 28         this.insertStuff(); 29       } 30 31      public static void main(String[] args){ 32        QTesterApp qt1 = new QTesterApp(); 33        QTesterApp qt2 = new QTesterApp(); 34        qt1.start(); 35        qt2.start(); 36      } // end main() 37    } // end QTesterApp class definition
image from book

Referring to example 17.10 — the ActiveQueue class gets its functionality from a LinkedList. The LinkedList class offers methods that allow you to insert objects at the beginning of the list and retrieve objects from the end of the list. The Vector reference _listeners will contain a collection of objects that have implemented the QueueListenerInterface. When a new element is added to an ActiveQueue object using the put() method on line 38, the fireQueueInsertionEvent() method is called. The fireQueueInsertionEvent() method, starting on line 54, uses an Iterator to step through the cloned _listeners Vector, calling the queueInsertionPerformed() method on each element.

Referring to example 17.12 — the QTesterApp class extends Thread and implements the QueueListenerInterface. It creates a static ActiveQueue object on line 6. This one static instance of ActiveQueue will be shared by all non-static instances of QTesterApp. The run() method beginning on line 27 simply calls the insertStuff() method, which inserts six Integer objects into the queue. The main() method starting on line 31 creates two QTesterApp instances and calls their start() methods. The results of running this program are shown in figure 17-20.

image from book
Figure 17-20: Results of Running Example 17.12

Quick Review

In Java collections framework up to and including 1.4.2 it is necessary to cast retrieved objects to their proper type if you need to call a method unique to that type. If you are calling methods that override Object class methods then casting is not required.

New data structures can be created from existing Java collections framework classes.




Java For Artists(c) The Art, Philosophy, and Science of Object-Oriented Programming
Java For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504052
EAN: 2147483647
Year: 2007
Pages: 452

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net