HashTable.java
Created with JBuilder
import java.util.Enumeration;  // Iterator pattern: to linearize the structure.
// import java.util.Iterator;  // This is the latest version of iterators in Java.

import lrs.*;

/**
* Hash table implementation of IDictionary (See Binary search tree).
* Uses external chaining.
* Readjusts the load factor by doubling the size of the table array each time
* the array is filled.
* Uses an abstract equivalence relation to match "equivalent" keys.
* @author Dung X. Nguyen - Copyright 2001 - All rights reserved.
* @since Nov. 28, 2001.
*/
public class HashTable implements IDictionary {
    /**
    * Key/Value Pair to be stored in hash table.
    */
    private static class KeyValPair {
        public Object key;
        public Object val;

        public KeyValPair(Object k, Object v) {
            key = k;
            val = v;
        }

        public String toString() {
            return "(" + key + "," + val + ")";
        }
    }

    /**
    * Equivalence for KeyValPair.
    */
    private static class EqKeyVal extends IEquivalence {
        private IEquivalence _eqKey;

        private EqKeyVal(IEquivalence eqKey) {
            _eqKey = eqKey;
        }

        public boolean equ (Object x, Object y) {
            return _eqKey.equ(((KeyValPair)x).key,  ((KeyValPair)y).key);
        }
    }

    private LRStruct[] _table = new LRStruct[1];
    private int _tableOccupancy = 0;
    private IAlgo _inserter;
    private IAlgo _deleter;
    private IAlgo _finder;

    public HashTable(IEquivalence eq) {
        IEquivalence eqKV = new EqKeyVal (eq);
        _inserter = new LRSInserter(eqKV );
        _deleter = new LRSDeleter(eqKV);
        _finder = new LRSFinder(eqKV);
        for (int i = 0; i < _table.length; i++) {
            _table[i] = new LRStruct();
        }
    }

    public Enumeration enumeration() {
        return new HashTableEnumeration();
    }

    /**
    * If there is an object associated with key
    * then this object is returned else null is returned.
    */
    public Object retrieve(Object key) {
        int index = key.hashCode() % _table.length;
        return _table[index].execute (_finder, key);
    }

    /**
    * Afterwards, find(key) returns null, and if there is
    * an object associated with key then this object is
    * returned else null is returned.
    */
    public Object remove (Object key) {
        int index = key.hashCode() % _table.length;
        Object value = _table[index].execute(_deleter, key);
        if (value == null) {
            _tableOccupancy--;
        }
        return value;
    }

    /**
    * (key, value) is stored in this container with no
    * duplication and such that find(key) returns value.
    */
    public void store(Object key, Object value) {
        // Create an array twice the size of _table, re-insert the existing data,
        // then re-assign _table to this new array.
        if (_tableOccupancy == _table.length) {
            int i;
            final LRStruct newTable[] = new LRStruct[2*_table.length];
            for (i = 0; i < newTable.length; i++) {
                newTable[i] = new LRStruct();
            }
            for (i = 0; i < _table.length; i++) {
                _table[i].execute (new IAlgo () {
                    public Object emptyCase(LRStruct h, Object inp) {
                        return null;
                    }

                    public Object nonEmptyCase(LRStruct h, Object inp) {
                        KeyValPair pair = (KeyValPair)h.getFirst ();
                        int index = pair.key.hashCode() % newTable.length;
                        newTable[index].execute(_inserter, pair);
                    }
                }, null);
            }
            _table = newTable;
        }
        int index = key.hashCode() % _table.length;
        _tableOccupancy++;
        _table[index].execute(_inserter, new KeyValPai(key, value));
    }

    /**
    * Inner class to iterate over the hash table and enumerate all the values
    * in the hash table.
    */
    class HashTableEnumeration implements Enumeration  {
        private LRStruct _lrs; // the current list.
        private int _index;    // the current index in the _table array.

        HashTableEnumeration() {
            _index = 0;
            _lrs = _table[_index];
        }

        public boolean hasMoreElements() {
            if (_index >= _table.length)
            {
              return false;
            }
            return ((Boolean)_lrs.execute(new IAlgo() {
                public Object emptyCase(LRStruct h, Object inp) {
                    _index++;
                    if (_index >= _table.length) {
                        return Boolean.FALSE;
                    }
                    _lrs = _table[index];
                    return _lrs.execute(this, null);
                }

                public Object nonEmptyCase(LRStruct h, Object inp) {
                    return Boolean.TRUE;
                }
            }, null)).booleanValue ();
        }

        public Object nextElement() {
            if (_index >= _table.length) {
                throw new java.util.NoSuchElementException ("No more elements!");
            }
            return _lrs.execute(new IAlgo() {
                // advance _lrs to the next LRStruct in the array, if any:
                public Object emptyCase(LRStruct h, Object inp) {
                    _index++;
                    if (_index >= _table.length) {
                        throw new java.util.NoSuchElementException ("No more elements!");
                    }
                    _lrs = _table[_index];  // _lrs is now the next list in the array.
                    return _lrs.execute (this, null);
                }

                public Object nonEmptyCase(LRStruct h, Object inp) {
                    KeyValPair res = (KeyValPair)h.getFirst();
                    _lrs = h.getRest(); // _lrs is now "pointing" to the next element in the list.
                    return res.val;
                }
            }, null);
        }
    }  // end of HashTableEnumeration
}


HashTable.java
Created with JBuilder