Data Structures, Algorithms, & Applications in Java
Chapter 11, Exercise 25
We would like to double the array size in case the new addition will cause the
loading factor to exceed the specified threshold.
To implement this strategy faithfully, we must first check if the
new addition is a duplicate. To avoid the cost of this check,
we double the table capacity whenever (size + 1)/capcity
exceeds the threshold. The code is given below.
public class HashTableWithDoubling extends HashTable
{
// double hash table capacity when loading factor
// exceeds threshold
private double threshold;
public HashTableWithDoubling(int theDivisor)
{
super(theDivisor);
threshold = 0.75;
}
public HashTableWithDoubling(double theThreshold)
{
super(11);
threshold = theThreshold;
}
/** insert an element with the specified key
* overwrite old element if there is already an
* element with the given key
* double table size when loading factor exceeds threshold
* overrides HashTable.put
* return old element (if any) with key theKey */
public Object put(Object theKey, Object theElement)
{
if (((double)(size + 1)) / table.length > threshold)
{// double table capacity, we assume theKey is not a duplicate
// doesn't hurt even if theKey is a duplicate
HashEntry [] oldTable = table;
// approximately double capacity, keeping length odd
table = new HashEntry [oldTable.length * 2 + 1];
divisor = table.length;
size = 0;
// insert old elements into new table
for (int i = 0; i < oldTable.length; i++)
if (oldTable[i] != null)
super.put(oldTable[i].key, oldTable[i].element);
}
// insert new item
return super.put(theKey, theElement);
}
}
A more efficient version is given below.
public class HashTableWithDoubling2 extends HashTable
{
// double hash table capacity when loading factor
// exceeds threshold
private double threshold;
public HashTableWithDoubling2(int theDivisor)
{
super(theDivisor);
threshold = 0.75;
}
public HashTableWithDoubling2(double theThreshold)
{
super(11);
threshold = theThreshold;
}
/** insert an element with the specified key
* overwrite old element if there is already an
* element with the given key
* double table size when loading factor exceeds threshold
* overrides hashTable.put
* return old element (if any) with key theKey */
public Object put(Object theKey, Object theElement)
{
if (((double)(size + 1)) / table.length > threshold)
{// double table capacity, we assume theKey is not a duplicate
// doesn't hurt even if theKey is a duplicate
HashEntry [] oldTable = table;
// approximately double capacity, keeping length odd
table = new HashEntry [oldTable.length * 2 + 1];
divisor = table.length;
// insert old elements into new table
for (int i = 0; i < oldTable.length; i++)
if (oldTable[i] != null)
{// enter oldTable[i] into new table
// find an empty bucket
int j = Math.abs(oldTable[i].key.hashCode()) % divisor;
while (table[j] != null)
j = (j + 1) % divisor; // next bucket
table[j] = oldTable[i];
}
}
// insert new item
return super.put(theKey, theElement);
}