/** Determines whether a key is valid. */
protected void checkKey(Object k) {
if (k == null) throw new InvalidKeyException("Invalid key: null.");
}
/** Hash function applying MAD method to default hash code. */
public int hashValue(Object key) {
return Math.abs(key.hashCode()*scale + shift) % N;
}
/** Returns the number of entries in the hash table. */
public int size() { return n; }
/** Returns whether or not the table is empty. */
public boolean isEmpty() { return (n == 0); }
/** Helper search method - returns index of found key or -index-1,
* where index is the index of an empty or available slot. */
protected int findEntry(Object key) throws InvalidKeyException {
int avail = 0;
checkKey(key);
int i = hashValue(key);
int j = i;
do {
if (A[i] == null) return -i - 1; // entry is not found
if (A[i] == AVAILABLE) { // bucket is deactivated
avail = i; // remember that this slot is available
i = (i + 1) % N; // keep looking
}
else if (T.isEqualTo(key,A[i].key())) // we have found our entry
return i;
else // this slot is occupied--we must keep looking
i = (i + 1) % N;
} while (i != j);
return -avail - 1; // entry is not found
}
/** Returns the value associated with a key. */
public Object get (Object key) throws InvalidKeyException {
int i = findEntry(key); // helper method for finding a key
if (i < 0) return null; // there is no value for this key
return A[i].value(); // return the found value in this case
}