package rebelsky.dict; import rebelsky.io.Pen; /** * A simple implementation of Hash tables. * * @author Samuel A. Rebelsky * @version 1.0 of November 2004 */ public class HashTable implements Dictionary { // +-------+--------------------------------------------------- // | Notes | // +-------+ /* This hash table is partially implemented. In particular, - the remove option is not implemented, - it fails to handle conflicts correctly, and - it does not expand itself when full */ // +--------+-------------------------------------------------- // | Fields | // +--------+ /** * The underlying array that stores all the key/value pairs * in the hash table. */ KeyedValue[] contents; /** * Something for printing observations. */ Pen observer; // +--------------+-------------------------------------------- // | Constructors | // +--------------+ /** * Build a new Hash table. */ public HashTable() { this.contents = new KeyedValue[10]; this.observer = new Pen(); } // HashTable() // +----------------+------------------------------------------ // | Public Methods | // +----------------+ /** * Find something in the dictionary. * * @pre * key should not be null. * @post * The value returned is the value most recently entered in the * dictionary by set(key, ...) with this key. * @exception NotFound * if the key is not in the dictionary (set has never been called with * this key). * @exception NullKey * If the key is null. Duh. */ public Object find(Object key) throws NotFound,NullKey { if (key == null) throw new NullKey(); int index = index(key); this.observe("The hash value for '" + key + "' is " + key.hashCode() + " and the index is " + index); if (this.contents[index] == null) throw new NotFound(); if (this.contents[index].key.equals(key)) return this.contents[index].value; // Note: What should we do if there's the wrong key? // Typically: Look in the next cell. // For now: Throw an exception. throw new NotFound("Unable to process key '" + key + "'"); } // find(Object) /** * Set a value in the dictionary. * * @pre * key is not null * @post * Subsequent calls to find(key) with the same key will * return value, provided there are no subsequent calls * to set with the same key. * @exception NullKey * If the key is null. Duh. */ public void set(Object key, Object value) throws NullKey { if (key == null) throw new NullKey(); int index = index(key); this.observe("The hash value for '" + key + "' is " + key.hashCode() + " and the index is " + index); // Empty cell: Put in a new keyed value. if (this.contents[index] == null) this.contents[index] = new KeyedValue(key, value); // Cell with same key: Replace the value. else if (this.contents[index].key.equals(key)) this.contents[index].value = value; // Different key. What should we do? // Typically: Look in the next cell. // For now: Replace the contents else this.contents[index] = new KeyedValue(key, value); } // set(Object,Object) /** * Remove a value from the dictionary. * * @pre * @post * @exception */ public void remove(Object key) { // STUB } // remove(Object) // +-----------------+----------------------------------------- // | Private Methods | // +-----------------+ /** * Make an observation (typically for testing or debugging). */ public void observe(String observation) { observer.println(" *** HT[" + observation + "] ***"); } // observe(String) /** * Compute an index. */ public int index(Object o) { return Math.abs(o.hashCode() % this.contents.length); } // index(Object) } // class HashTable