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 }