1. Introduction
A HashTable is a data structure that offers a mechanism to store key-value pairs. The primary advantage of using a HashTable is its ability to access stored values in constant time O(1), provided the keys are uniformly distributed. This rapid access is achievable because of the unique key index (produced by a hash function) that corresponds to a specific location in the HashTable. In cases where two keys yield the same hash value, collisions are handled.
Let’s delve into the implementation of a HashTable in Java.
2. Program Steps
1. Define a class named Entry to represent key-value pairs.
2. Implement the HashTable class which will provide functionalities such as put, get, and remove.
3. Use an array of Entry objects to store data.
4. For simplicity, handle collisions using linked list chaining.
5. Test the HashTable with various operations.
3. Code Program
class Entry<K, V> {
K key;
V value;
Entry<K, V> next;
public Entry(K key, V value, Entry<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
}
class HashTable<K, V> {
private Entry<K, V>[] table;
private int capacity = 128;
public HashTable() {
table = new Entry[capacity];
}
// Function to calculate hash value
private int hash(K key) {
return Math.abs(key.hashCode()) % capacity;
}
// Insert into HashTable
public void put(K key, V value) {
int index = hash(key);
Entry<K, V> newEntry = new Entry<>(key, value, null);
if (table[index] == null) {
table[index] = newEntry;
} else {
Entry<K, V> previous = null;
Entry<K, V> current = table[index];
while (current != null) {
if (current.key.equals(key)) {
if (previous == null) {
newEntry.next = current.next;
table[index] = newEntry;
return;
} else {
newEntry.next = current.next;
previous.next = newEntry;
return;
}
}
previous = current;
current = current.next;
}
previous.next = newEntry;
}
}
// Get a value from HashTable
public V get(K key) {
int index = hash(key);
Entry<K, V> current = table[index];
while (current != null) {
if (current.key.equals(key)) {
return current.value;
}
current = current.next;
}
return null;
}
// Remove key-value pair from HashTable
public void remove(K key) {
int index = hash(key);
Entry<K, V> previous = null;
Entry<K, V> current = table[index];
while (current != null) {
if (current.key.equals(key)) {
if (previous == null) {
table[index] = table[index].next;
return;
} else {
previous.next = current.next;
return;
}
}
previous = current;
current = current.next;
}
}
}
public class Main {
public static void main(String[] args) {
HashTable<String, Integer> hashTable = new HashTable<>();
hashTable.put("One", 1);
hashTable.put("Two", 2);
hashTable.put("Three", 3);
System.out.println("Value for 'One': " + hashTable.get("One"));
System.out.println("Value for 'Two': " + hashTable.get("Two"));
hashTable.remove("Two");
System.out.println("Value for 'Two' after removal: " + hashTable.get("Two"));
}
}
Output:
Value for 'One': 1 Value for 'Two': 2 Value for 'Two' after removal: null
4. Step By Step Explanation
1. The program begins with the definition of an Entry class which encapsulates the key-value pairs and a reference to the next entry. This aids in handling collisions.
2. The HashTable class uses an array named table to store the Entry objects. The array's index is determined by the hash value of the key.
3. The hash function computes the hash value of a given key, ensuring it fits within the bounds of the array capacity.
4. The put method inserts or updates a key-value pair. In cases of collisions, linked list chaining is used.
5. The get method retrieves the value associated with a particular key.
6. The remove method deletes a key-value pair from the HashTable.
7. In the Main class, the HashTable is tested by inserting some values, fetching them, and performing removal operations.
8. The output reflects the HashTable's ability to store, retrieve, and remove key-value pairs effectively.