// Textbook fragment 09.03 /** A hash table with linear probing and the MAD hash function */ import java.util.Iterator; public class HashTableMap implements Map { public static class HashEntry implements Entry { protected K key; protected V value; public HashEntry(K k, V v) { key = k; value = v; } public V getValue() { return value; } public K getKey() { return key; } public V setValue(V val) { V oldValue = value; value = val; return oldValue; } public boolean equals(Object o) { HashEntry ent; try { ent = (HashEntry) o; } catch (ClassCastException ex) { return false; } return (ent.getKey() == key) && (ent.getValue() == value); } } protected Entry AVAILABLE = new HashEntry(null, null); // marker protected int n = 0; // number of entries in the dictionary protected int capacity; // capacity of the bucket array protected Entry[] bucket;// bucket array protected int scale, shift; // the shift and scaling factors /** Creates a hash table with initial capacity 1023. */ public HashTableMap() { this(1023); } /** Creates a hash table with the given capacity. */ public HashTableMap(int cap) { capacity = cap; bucket = (Entry[]) new Entry[capacity]; // safe cast java.util.Random rand = new java.util.Random(); scale = rand.nextInt(capacity-1) + 1; shift = rand.nextInt(capacity); } /** Determines whether a key is valid. */ protected void checkKey(K k) { if (k == null) throw new InvalidKeyException("Invalid key: null."); } /** Hash function applying MAD method to default hash code. */ public int hashValue(K key) { return Math.abs(key.hashCode()*scale + shift) % capacity; }