|
|
|
public class Entry { public String key; // String typed key (for now) public Integer value; // Integer typed value (for now) /** Constructor */ public Entry( String k, Integer v) { key = k; value = v; } /** Returns the key stored in this entry. */ public String getKey() { return key; // You would need this when using private variables } /** Returns the value stored in this entry. */ public Integer getValue() { return value; } public Integer setValue(Integer val) { Integer oldValue = value; value = val; // Update value return oldValue; // Return old value } } |
|
public Entry[] bucket; // The hash table (buckets) public int capacity; // capacity == bucket.length public int NItems; // NItems = # entries in hash table |
|
|
public class HashMap { public Entry[] bucket; // The hash table (buckets) public int capacity; // capacity == bucket.length public int NItems; // NItems = # entries in hash table public int MAD_p; public int MAD_a; public int MAD_b; /* =============================================================== General Constructor: initialize prime number p Create an array (bucket) of given size =============================================================== */ public HashMap(int p, int MapArraySize) { capacity = MapArraySize; bucket = new Entry[ capacity ]; // Create the array ! NItems = 0; java.util.Random rand = new java.util.Random(); // Use to generate random numbers... MAD_p = p; // Prime number in MAD MAD_a = rand.nextInt(MAD_p-1) + 1; // Multiplier in MAD MAD_b = rand.nextInt(MAD_p); // Shift amount in MAD } ...... } |
/* =============================================================== Common Constructor: pick the default prime number 109345121 Create an array (bucket) of given size =============================================================== */ public HashMap(int MapArraySize) { this( 109345121, MapArraySize ); // Calls general constructor } |
public HashMap( ) // No parameters ! { this( 109345121, 1000 ); // Default array size = 1000 } |
public class HashMap { public Entry[] bucket; // The hash table (buckets) public int capacity; // capacity == bucket.length public int NItems; // NItems = # entries in hash table public int MAD_p; public int MAD_a; public int MAD_b; /* =============================================================== General Constructor: initialize prime number p Create an array (bucket) of given size =============================================================== */ public HashMap(int p, int MapArraySize) { capacity = MapArraySize; bucket = new Entry[ capacity ]; NItems = 0; java.util.Random rand = new java.util.Random(); MAD_p = p; // Prime number in MAD MAD_a = rand.nextInt(MAD_p-1) + 1; // Multiplier in MAD MAD_b = rand.nextInt(MAD_p); // Shift amount in MAD } /* =============================================================== Common Constructor: pick the default prime number 109345121 Create an array (bucket) of given size =============================================================== */ public HashMap(int MapArraySize) { this( 109345121, MapArraySize ); // Calls general constructor } public HashMap() { this( 109345121, 1000 ); // Default array size = 1000 } ...... } |
|
/* =============================================================== Hash function: 1. uses the Hash Code inside the String class 2. uses the MAD compression function hash index = [ (a*HashCode + b) % p ] % N =============================================================== */ public int hashValue(String key) { int x = key.hashCode(); // String has a built-in hashCode() !!! return (int) ( ( Math.abs( MAD_a*x + MAD_b ) % MAD_p ) % capacity ); } |
|
|
/* =============================================== The entries are of the format: String key, Integer value So the return value is: Integer ! =============================================== */ public Integer get(String k) { int found = findEntry(k); // Find the array index for the key k // If found > 0, index_for_key is the index if ( found > 0 ) { // Found the key in the hash table return bucket[index_for_key].getValue(); // return value } else { return null; // Key not found } } |
|
|
int findEntry(String key) // I use key instead of k to make the key explicit { if ( key == null ) return ERROR; i = hashValue( key ); // Start the search at index i while ( search did not wrap around ) { if ( bucket[i] contains an entry ) { // 2 possibilities: // 1. entry has a value (key, value) // 2. entry contains special EMPTY marker (see: click here) if ( bucket[i] == EMPTY Marker ) // Entry contains the special EMPTY marker { // entry was deleted previously Remember the location of the FIRST special EMPTY marker ********* // For the reason, see: click here i = (i + 1) % capacity; // Continue search } else ( bucket[i].key == key ) // FOUND the key !!! { return FOUND ; (and location i contains the key !) ******** } } else // Search reach a HOLE -> key not found -- STOP { return NOT FOUND ; (and location i can be used to STORE the key !) ******** } } return NOT FOUND; // Search wrapped around --> not found ! **** This case can be a big problem: the hash table may be FULL **** We will add code to make sure the hash table will never fill up later } |
/* ====================================================================
findEntry(key): find index of the array for given key
Return value:
1 ==> key is found in the hash table
Set index_for_key such that: Entry[index_for_key].key == key
0 ==> key is NOT found
Entry[index_for_key] is where you can STORE the key
==================================================================== */
public int findEntry(String key)
{
int i;
int start;
if ( key == null )
{
index_for_key = -1; // Error
return ( -1 ); // Not found
}
i = hashValue(key); // Start location to look for key
start = i; // Remember the start location (to detect wrap around)
index_for_key = -1; // Flag "no empty slow found" condition.
do
{
Entry e;
e = bucket[i]; // Testing bucket[i]...
if ( e != null )
{
// bucket[i] contains something...
// Possibilities:
// 1. the special EMPTY marker --> remember FIRST marker and
// go to next entry
// 2. contains the search key --> return FOUND
// 3. contains some other key --> go to next entry
if ( e == AVAILABLE )
{ // entry in bucket was deleted
if ( index_for_key < 0 )
index_for_key = i; // remember the FIRST available slot
}
else if ( key.equals(e.getKey()) ) // we have found our key
{
index_for_key = i;
return 1; // key found !!
}
i = (i + 1) % capacity; // Check the next slot... if any
}
else
{ /* --------------------------------------------------
bucket[i] contains NULL: chain is broken
We know the key is not in hash table
-------------------------------------------------- */
if ( index_for_key < 0 ) // Did we found an EMPTY marker ?
index_for_key = i; // No --> insert key here if needed
return(0); // Return "not found" indication
}
} while ( i != start ); // Stop when you wrap around
return 0; // Not found (wrapped around...)
}
|
public Integer put (String key, int value) { int found = findEntry(key); //find the appropriate spot for this entry if ( found > 0 ) // key found ===> update value { // Note: // The variable index_for_key is set to the bucket containing the key // i.e.: bucket[index_for_key].key == key Integer oldValue = bucket[index_for_key].setValue(value);// set new value return ( oldValue ); // Return old value } /* =============================================================== Key not found ==> Insert (key, value) in bucket[index_for_key] =============================================================== */ if ( index_for_key >= 0 ) { bucket[index_for_key] = new Entry(key, value); // Insert !!! NItems++; // One more entry... } else { // Hash table is FULL !!! System.out.println("ERROR: Hash Table is FULL !!!"); } return null; // there was no previous value } |
public Integer remove (String key) { int found = findEntry(key); // find this key first if ( found == 0 ) // Not found.... return null; // nothing to remove **** If execution reach here, then key was found ===> Delete the entry ! // Note: // The variable index_for_key is set to the bucket containing the key // i.e.: bucket[index_for_key].key == key Integer toReturn = bucket[index_for_key].getValue(); // Remember old value bucket[index_for_key] = AVAILABLE; // mark this slot as deactivated NItems--; // One less entry... return toReturn; // Return old value } |
Here is my own HashMap in Java.
How to run the program:
|
|
|
I.e.: We must traverse all elements in an array !!! (which is easy to do....)
public Collection |
|