|
|
|
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 |
|