/******************************************************************************* * @file ExtHash.java * * @author John Miller */ import java.io.*; import java.lang.reflect.Array; import static java.lang.System.out; import java.util.*; /******************************************************************************* * This class provides hash maps that use the Extendable Hashing algorithm. Buckets * are allocated and stored in a hash table and are referenced using directory dir. */ public class ExtHash extends AbstractMap implements Serializable, Cloneable, Map { /** The number of slots (for key-value pairs) per bucket. */ private static final int SLOTS = 4; /** The class for type K. */ private final Class classK; /** The class for type V. */ private final Class classV; /*************************************************************************** * This inner class defines buckets that are stored in the hash table. */ private class Bucket { int nKeys; K [] key; V [] value; @SuppressWarnings("unchecked") Bucket () { nKeys = 0; key = (K []) Array.newInstance (classK, SLOTS); value = (V []) Array.newInstance (classV, SLOTS); } // constructor } // Bucket inner class /** The hash table storing the buckets (buckets in physical order) */ private final List hTable; /** The directory providing access paths to the buckets (buckets in logical oder) */ private final List dir; /** The modulus for hashing (= 2^D) where D is the global depth */ private int mod; /** The number of buckets */ private int nBuckets; /** Counter for the number buckets accessed (for performance testing). */ private int count = 0; /*************************************************************************** * Construct a hash table that uses Extendable Hashing. * @param classK the class for keys (K) * @param classV the class for keys (V) * @param initSize the initial number of buckets (a power of 2, e.g., 4) */ public ExtHash (Class _classK, Class _classV, int initSize) { classK = _classK; classV = _classV; hTable = new ArrayList <> (); // for bucket storage dir = new ArrayList <> (); // for bucket access mod = nBuckets = initSize; } // ExtHash /*************************************************************************** * Return a set containing all the entries as pairs of keys and values. * @return the set view of the map */ public Set > entrySet () { Set > enSet = new HashSet <> (); //-----------------\\ // TO BE IMPLEMENTED \\ //---------------------\\ return enSet; } // entrySet /*************************************************************************** * Given the key, look up the value in the hash table. * @param key the key used for look up * @return the value associated with the key */ public V get (Object key) { int i = h (key); Bucket b = dir.get (i); //-----------------\\ // TO BE IMPLEMENTED \\ //---------------------\\ return null; } // get /*************************************************************************** * Put the key-value pair in the hash table. * @param key the key to insert * @param value the value to insert * @return null (not the previous value) */ public V put (K key, V value) { int i = h (key); Bucket b = dir.get (i); //-----------------\\ // TO BE IMPLEMENTED \\ //---------------------\\ return null; } // put /*************************************************************************** * Return the size (SLOTS * number of buckets) of the hash table. * @return the size of the hash table */ public int size () { return SLOTS * nBuckets; } // size /*************************************************************************** * Print the hash table. */ private void print () { out.println ("Hash Table (Extendable Hashing)"); out.println ("-------------------------------------------"); //-----------------\\ // TO BE IMPLEMENTED \\ //---------------------\\ out.println ("-------------------------------------------"); } // print /*************************************************************************** * Hash the key using the hash function. * @param key the key to hash * @return the location of the directory entry referencing the bucket */ private int h (Object key) { return key.hashCode () % mod; } // h /*************************************************************************** * The main method used for testing. * @param the command-line arguments (args [0] gives number of keys to insert) */ public static void main (String [] args) { ExtHash ht = new ExtHash <> (Integer.class, Integer.class, 11); int nKeys = 30; if (args.length == 1) nKeys = Integer.valueOf (args [0]); for (int i = 1; i < nKeys; i += 2) ht.put (i, i * i); ht.print (); for (int i = 0; i < nKeys; i++) { out.println ("key = " + i + " value = " + ht.get (i)); } // for out.println ("-------------------------------------------"); out.println ("Average number of buckets accessed = " + ht.count / (double) nKeys); } // main } // ExtHash class