package containers; import java.util.Enumeration; /** * A container implemented using a hash table. Collisions are handled * using chaining. The chains are implemented as LRSContainers. * * Uses the method hashCode() defined by class Object as the hash * function. Any class may override this method with a new * implementation. * * Version 1. * * @author Alan L. Cox * @since 04/27/01 */ public class HashTable implements IContainer { /* * Initialize _table to reference a single-element array of * IContainer, containing in its single element a reference to an * empty LRSContainer. */ private IContainer _table[] = { new LRSContainer() }; private int _tableOccupancy = 0; private double _loadFactor; public HashTable(double loadFactor) { _loadFactor = loadFactor; } /** * If there is an object associated with key * then this object is returned else null is returned. * * This method is O(1) in the expected case and O(n) in the worst * case. * * @param key the key to find * @return the value found */ public Object find(Object key) { int index = key.hashCode() % _table.length; return _table[index].find(key); } /** * Afterwards, find(key) returns null, and if there is * an object associated with key then this object is * returned else null is returned. * * This method is O(1) in the expected case and O(n) in the worst * case. * * @param key the key to remove * @return the value removed */ public Object remove(Object key) { int index = key.hashCode() % _table.length; Object value = _table[index].remove(key); if (value != null) _tableOccupancy--; return value; } /** * (key, value) is stored in this container with no * duplication and such that find(key) returns value. * * This method is O(1) in both the expected case and the worst * case if we amortize the cost of doubling the hash table over * subsequent insert()'s. * * @param key the key to insert * @param valuethe value to insert */ public void insert(Object key, Object value) { if (_tableOccupancy >= (_loadFactor * _table.length)) { int i; IContainer newTable[] = new IContainer[2*_table.length]; for (i = 0; i < newTable.length; i++) newTable[i] = new LRSContainer(); for (i = 0; i < _table.length; i++) { Enumeration e = _table[i].enumeration(); while (e.hasMoreElements()) { KeyValuePair pair = (KeyValuePair) e.nextElement(); int index = pair.getKey().hashCode() % newTable.length; newTable[index].insert(pair.getKey(), pair.getValue()); } } _table = newTable; } int index = key.hashCode() % _table.length; _tableOccupancy++; _table[index].insert(key, value); } /** * Returns an Enumeration of the container. The objects returned * by nextElement() are KeyValuePair's. * * @return an Enumeration of the container */ public Enumeration enumeration() { return new Enumeration() { private Enumeration _e = _table[0].enumeration(); private int _index = 1; public boolean hasMoreElements() { for (;;) { if (_e.hasMoreElements()) return true; if (_index >= _table.length) return false; _e = _table[_index].enumeration(); _index++; } } public Object nextElement() { for (;;) { if (_e.hasMoreElements()) return _e.nextElement(); if (_index >= _table.length) return null; _e = _table[_index].enumeration(); _index++; } } }; } public static void main(String args[]) { HashTable ht = new HashTable(1.5); ht.insert(new Integer(13), "13"); ht.insert(new Integer(19), "19"); ht.insert(new Integer(21), "21"); ht.insert(new Integer(2), "2"); ht.insert(new Integer(32), "32"); ht.insert(new Integer(37), "37"); ht.insert(new Integer(73), "73"); ht.insert(new Integer(75), "75"); ht.insert(new Integer(57), "57"); System.out.println("value = " + ht.find(new Integer(2))); System.out.println("value = " + ht.find(new Integer(32))); System.out.println("value = " + ht.find(new Integer(37))); System.out.println("-----"); Enumeration e = ht.enumeration(); while (e.hasMoreElements()) { KeyValuePair pair = (KeyValuePair) e.nextElement(); System.out.println("value = " + pair.getValue()); } } }