Java Utilities Package

The java.util package has a number of utility classes

Vector class create array-like objects that can grow and shrink dynamically
Stack class offers conventional stack operations push and pop along with several others
Dictionary class gives us the framework for storing keyed data in tables and retrieving the data
Hashtable class a technique for rapidly storing and retrieving information from tables
Properties class enables us to create persistent hash tables i.e hashtables that can be written and read from a file
Random class a collection of rendom number capabilities

Vector Class and Enumeration

Before I begin, the Enumeration interface has been superceded by the Iterator interface in more recent version of Java, but there is still alot of code in the wild that still uses the Enumeration interface, so I will explain how to use it here.

I have also discussed various collection methods in object collections, so take a peek to see all the options you have available.

Java arrays are fixed in size, they cannot grow or shrink, thus the Vector class offers an array-like structure that can dynamically grow in response to an applications changing storage requirements.

Vectors have capacity which is the space that has been reserved for the array, if a Vector needs to grow, it grows by an increment that you specify or by the default assumed by the system. If you do not specify a capacity increment, the system will automatically double the size of the Vector each time additional capacity is needed.

Vectors can store objects, thus a reference to an object of any class type can be stored in a Vector.

Vector example
// VectorTest Class

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class VectorTest extends JFrame {

   public VectorTest()
   {
      super( "Vector Example" );

      final JLabel status = new JLabel();
      Container c = getContentPane();
      final Vector v = new Vector( 1 );            

      c.setLayout( new FlowLayout() );

      c.add( new JLabel( "Enter a string" ) );
      final JTextField input = new JTextField( 10 );
      c.add( input );       

      JButton addBtn = new JButton( "Add" );
      addBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               v.addElement( input.getText() );
               status.setText( "Added to end: " + input.getText() );
               input.setText( "" ); 
            }
         }
      );         
      c.add( addBtn );      // add the input value

      JButton removeBtn = new JButton( "Remove" );
      removeBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               if ( v.removeElement( input.getText() ) )
                  status.setText( "Removed: " + input.getText() );
               else
                  status.setText( input.getText() + " not in vector" );
            }
         }
      );
      c.add( removeBtn );   

      JButton firstBtn = new JButton( "First" );
      firstBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               try {
                  status.setText( "First element: " + v.firstElement() );
               }
               catch ( NoSuchElementException exception ) {
                  status.setText( exception.toString() );
               }
            }
         }
      );
      c.add( firstBtn );    

      JButton lastBtn = new JButton( "Last" );
      lastBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               try {
                  status.setText( "Last element: " + v.lastElement() );
               }
               catch ( NoSuchElementException exception ) {
                  status.setText( exception.toString() );
               }
            }
         }
      );
      c.add( lastBtn );     

      JButton emptyBtn = new JButton( "Is Empty?" );
      emptyBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( v.isEmpty() ? "Vector is empty" : "Vector is not empty" );
            }
         }
      );
      c.add( emptyBtn );    

      JButton containsBtn = new JButton( "Contains" );
      containsBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               String searchKey = input.getText();

               if ( v.contains( searchKey ) ) 
                  status.setText( "Vector contains " + searchKey );
               else
                  status.setText( "Vector does not contain " + searchKey );
            }
         }
      );
      c.add( containsBtn ); 

      JButton locationBtn = new JButton( "Location" );
      locationBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( "Element is at location " + v.indexOf( input.getText() ) );
            }
         }
      );
      c.add( locationBtn );

      JButton trimBtn = new JButton( "Trim" );
      trimBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               v.trimToSize();
               status.setText( "Vector trimmed to size" );
            }
         }
      );
      c.add( trimBtn );     

      JButton statsBtn = new JButton( "Statistics" );
      statsBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( "Size = " + v.size() + "; capacity = " + v.capacity() );
            }
         }
      );
      c.add( statsBtn );    

      JButton displayBtn = new JButton( "Display" );
      displayBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Enumeration enum = v.elements();
               StringBuffer buf = new StringBuffer();
        
               while ( enum.hasMoreElements() )
                  buf.append( enum.nextElement() ).append( "  " );
       
               JOptionPane.showMessageDialog( null,
                  buf.toString(), "Display",
                  JOptionPane.PLAIN_MESSAGE );
            }
         }
      );
      c.add( displayBtn );
      c.add( status );

      setSize( 300, 200 );
      show();
   }

   public static void main( String args[] )
   {
      VectorTest app = new VectorTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Stack Class

There is not point in reinventing the wheel, I have already discussed how to implement a stack but Java offers a Stack class which extends Vector to implement a stack data structure. Like Vector a Stack can store objects, thus a reference to an object of any class type can be stored in a Stack.

Stack example
// StackTest Class

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class StackTest extends JFrame {

   public StackTest()
   {
      super( "Stacks" );

      Container c = getContentPane();

      final JLabel status = new JLabel();
      final Stack s = new Stack();

      c.setLayout( new FlowLayout() );
      c.add( new JLabel( "Enter a string" ) );
      final JTextField input = new JTextField( 10 );
      c.add( input );      

      JButton pushBtn = new JButton( "Push" );
      pushBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( "Pushed: " + 
                  s.push( input.getText() ) );
            }
         }
      );
      c.add( pushBtn );    

      JButton popBtn = new JButton( "Pop" );
      popBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               try {
                  status.setText( "Popped: " + s.pop() );
               }
               catch ( EmptyStackException exception ) {
                  status.setText( exception.toString() );
               }
            }
         }
      );
      c.add( popBtn );     

      JButton peekBtn = new JButton( "Peek" );
      peekBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               try {
                  status.setText( "Top: " + s.peek() );
               }
               catch ( EmptyStackException exception ) {
                  status.setText( exception.toString() );
               }
            }
         }
      );
      c.add( peekBtn );     

      JButton emptyBtn = new JButton( "Is Empty?" );
      emptyBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( s.empty() ?  "Stack is empty" : "Stack is not empty" );
            }
         }
      );
      c.add( emptyBtn );   

      JButton searchBtn = new JButton( "Search" );
      searchBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               String searchKey = input.getText();
               int result = s.search( searchKey );

               if ( result == -1 ) 
                  status.setText( searchKey + " not found" );
               else
                  status.setText( searchKey + " found at element " + result );                     
            }
         }
      );
      c.add( searchBtn );  

      JButton displayBtn = new JButton( "Display" );
      displayBtn.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Enumeration enum = s.elements();
               StringBuffer buf = new StringBuffer();
        
               while ( enum.hasMoreElements() )
                  buf.append( enum.nextElement() ).append( " " );
       
               JOptionPane.showMessageDialog( null,
                   buf.toString(), "Display",
                   JOptionPane.PLAIN_MESSAGE );
            }
         }
      );
      c.add( displayBtn );
      c.add( status );

      setSize( 675, 100 );
      show();
   }

   public static void main( String args[] )
   {
      StackTest app = new StackTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Dictionary Class

A dictionary maps keys to values, A key is supplied and the dictionary returns a value. Dictionary is an abstract class and is the superclass of the hashtable class. Each key in the dictionary is unique, the data structure is simular to a dictionary of words and definitions, the word is the key and the definition is the value.

Hashtable Class

I have already explained hashing in object collections, Java offers the Hashtable class, one problem with hashing is when collisions occur (two different keys in the same cell (or element)), since we cannot store two different records in the same space, we need to find an alternative home for all records beyond the first that hash to a particular array subscript. There are many schema's for doing this, one way is to hash again, another scheme uses one hash to locate the first first candidate cell, if that cell is occupied, successive cells are search linearly until an available cell is found. The most popular solution is to have each cell of the table be a hash bucket typically a linked list of all key/value pairs that hash to that cell. This is the solution that the hashtable class offers.

One factor that affects performance of hashing schemes is called the load factor, this is the ratio of the number of occupied cells in the hash table to the size of the hash table. The closer this ratio gets to 1.0 the greater the change of collisions.

Increase load factor By increaing the load factor we get better memory utilization, but the program runs slower due to increased hashing collisions.
Decrease load factor By decreasing the load factor we get better program speed because of reduced hashing collisions, but we get poorer memory utilization because a larger portion of the hash remains empty.

Now for the example

Hashtable example
// HashtableTest Class

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HashtableTest extends JFrame {

   public HashtableTest()
   {
      super( "Hashtable Example" );

      final JLabel status = new JLabel();
      final Hashtable table = new Hashtable();
      final JTextArea display = new JTextArea( 4, 20 );
      display.setEditable( false );

      JPanel northPanel = new JPanel();
      northPanel.setLayout( new BorderLayout() );
      JPanel northSubPanel = new JPanel();
      northSubPanel.add( new JLabel( "First name" ) );
      final JTextField fName = new JTextField( 8 );
      northSubPanel.add( fName );

      northSubPanel.add( new JLabel( "Last name (key)" ) );
      final JTextField lName = new JTextField( 8 );
      northSubPanel.add( lName );
      northPanel.add( northSubPanel, BorderLayout.NORTH );
      northPanel.add( status, BorderLayout.SOUTH );

      JPanel southPanel = new JPanel();
      southPanel.setLayout( new GridLayout( 2, 5 ) );
      JButton put = new JButton( "Put" );
      put.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Employee emp = new Employee( fName.getText(), lName.getText() );
               Object val = table.put( lName.getText(), emp );

               if ( val == null )
                  status.setText( "Put: " + emp.toString() );
               else
                  status.setText( "Put: " + emp.toString() + "; Replaced: " + val.toString() );
            }
         }
      );
      southPanel.add( put );

      JButton get = new JButton( "Get" );
      get.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Object val = table.get( lName.getText() );
             
               if ( val != null )
                  status.setText( "Get: " + val.toString() );
               else
                  status.setText( "Get: " + lName.getText() + " not in table" );
            }
         }
      );
      southPanel.add( get );

      JButton remove = new JButton( "Remove" );
      remove.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Object val = table.remove( lName.getText() );
             
               if ( val != null )
                  status.setText( "Remove: " + val.toString() );
               else
                  status.setText( "Remove: " + lName.getText() + " not in table" );                     
            }
         }
      );
      southPanel.add( remove );

      JButton empty = new JButton( "Empty" );
      empty.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( "Empty: " + table.isEmpty() );
            }
         }
      );
      southPanel.add( empty );

      JButton containsKey = new JButton( "Contains key" );
      containsKey.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               status.setText( "Contains key: " + table.containsKey( lName.getText() ) );
            }
         }
      );
      southPanel.add( containsKey );

      JButton clear = new JButton( "Clear table" );
      clear.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               table.clear();
               status.setText( "Clear: Table is now empty" );
            }
         }
      );
      southPanel.add( clear );

      JButton listElems = new JButton( "List objects" );
      listElems.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               StringBuffer buf = new StringBuffer();

               for ( Enumeration enum = table.elements(); enum.hasMoreElements(); )
                  buf.append( enum.nextElement() ).append( '\n' );

               display.setText( buf.toString() );
            }
         }
      );
      southPanel.add( listElems );

      JButton listKeys = new JButton( "List keys" );
      listKeys.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               StringBuffer buf = new StringBuffer();

               for ( Enumeration enum = table.keys(); enum.hasMoreElements(); )
                  buf.append( enum.nextElement() ).append( '\n' );

                  JOptionPane.showMessageDialog( null,
                     buf.toString(), "Display",
                     JOptionPane.PLAIN_MESSAGE );
            }
         }
      );
      southPanel.add( listKeys );
      Container c = getContentPane();
      c.add( northPanel, BorderLayout.NORTH );
      c.add( new JScrollPane( display ), BorderLayout.CENTER );
      c.add( southPanel, BorderLayout.SOUTH );

      setSize( 540, 300 );
      show();
   }

   public static void main( String args[] )
   {
      HashtableTest app = new HashtableTest();

      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

class Employee {
   private String first, last;

   public Employee( String fName, String lName )
   {
      first = fName;
      last = lName;
   }

   public String toString() { return first + " " + last; }
}

Properties Class

A properties Object is a persistent Hashtable, by persistent we to that the Hashtable is written to a file, then read back. In fact most objects in Java can now be output and input with Java's serialization.

Properties example
// PropertiesTest Class

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class PropertiesTest extends JFrame {
   private JLabel status;
   private Properties table;
   private JTextArea display;

   public PropertiesTest()
   {
      super( "Properties Test" );

      table = new Properties();
      Container c = getContentPane();
      JPanel northPanel = new JPanel();
      northPanel.setLayout( new BorderLayout() );
      JPanel northSubPanel = new JPanel();
      JPanel southPanel = new JPanel();

      northSubPanel.add( new JLabel( "Property value" ) );
      final JTextField propVal = new JTextField( 10 );
      northSubPanel.add( propVal );
      northPanel.add( northSubPanel, BorderLayout.NORTH );

      northSubPanel.add( new JLabel( "Property name (key)" ) );
      final JTextField propName = new JTextField( 10 );
      northSubPanel.add( propName );

      display = new JTextArea( 4, 35 );     

      JButton put = new JButton( "Put" );
      put.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Object val = table.put( propName.getText(), propVal.getText() );

               if ( val == null )
                  showStatus( "Put: " + propName.getText() + " " + propVal.getText() );
               else
                  showStatus( "Put: " + propName.getText() + " " + propVal.getText() +
                              "; Replaced: " + val.toString() );
                              
               listProperties();
            }
         }
      );
      southPanel.setLayout( new GridLayout( 1, 5 ) );
      southPanel.add( put );

      JButton clear = new JButton( "Clear" );
      clear.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               table.clear();
               showStatus( "Table in memory cleared" );
               listProperties();
            }
         }
      );
      southPanel.add( clear );

      JButton getProperty = new JButton( "Get property" );
      getProperty.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               Object val = table.getProperty( propName.getText() );
             
               if ( val != null )
                  showStatus( "Get property: " + propName.getText() + " " + val.toString() );
               else
                  showStatus( "Get: " + propName.getText() + " not in table" );

               listProperties();
            }
         }
      );
      southPanel.add( getProperty );

      JButton save = new JButton( "Save" );
      save.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               try {
                  FileOutputStream output;

                  output = new FileOutputStream( "props.dat" );
                  table.store( output, "Sample Properties" );
                  output.close();
                  listProperties();
               }
               catch( IOException ex ) {
                  showStatus( ex.toString() );
               }
            }
         }
      );
      southPanel.add( save );

      JButton load = new JButton( "Load" );
      load.addActionListener(
         new ActionListener() {
            public void actionPerformed( ActionEvent e )
            {
               try {
                  FileInputStream input;

                  input = new FileInputStream( "props.dat" );
                  table.load( input );
                  input.close();
                  listProperties();
               }
               catch( IOException ex ) {
                  showStatus( ex.toString() );
               }
            }
         }
      ); 
      southPanel.add( load );

      status = new JLabel();
      northPanel.add( status, BorderLayout.SOUTH );

      c.add( northPanel, BorderLayout.NORTH );
      c.add( new JScrollPane( display ), BorderLayout.CENTER );
      c.add( southPanel, BorderLayout.SOUTH );

      setSize( 550, 225 );
      show();
   }

   public void listProperties()
   {
      StringBuffer buf = new StringBuffer();
      String pName, pVal;

      Enumeration enum = table.propertyNames();

      while( enum.hasMoreElements() ) {
         pName = enum.nextElement().toString();
         pVal = table.getProperty( pName );
         buf.append( pName ).append( '\t' );
         buf.append( pVal ).append( '\n' );
      }

      display.setText( buf.toString() );
   }

   public void showStatus( String s )
   {
      status.setText( s );
   }

   public static void main( String args[] )
   {
      PropertiesTest app = new PropertiesTest();
      app.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e )
            {
               System.exit( 0 );
            }
         }
      );
   }
}

Random Class

Java provides extensive additional random number generation capabilities in class Random. The repeatablility of random numbers that occurs when the seed value is used is useful for testing and debugging, however when in a production evnironment you used remove the seed value.

Random example Random r = new Random();
Random with seed value example Random rsv = new Random( <seed value> );
rsv.setSeed( <new seed value> );            ## resets the seed value