Practical Hash Implementation
Custom Hash Implementation Strategies
1. Creating a Custom Hash Table
public class CustomHashTable<K, V> {
private static final int DEFAULT_CAPACITY = 16;
private Entry<K, V>[] buckets;
private int size;
public CustomHashTable() {
buckets = new Entry[DEFAULT_CAPACITY];
size = 0;
}
public void put(K key, V value) {
int index = calculateIndex(key);
Entry<K, V> newEntry = new Entry<>(key, value);
if (buckets[index] == null) {
buckets[index] = newEntry;
} else {
Entry<K, V> current = buckets[index];
while (current.next != null) {
if (current.key.equals(key)) {
current.value = value;
return;
}
current = current.next;
}
current.next = newEntry;
}
size++;
}
private int calculateIndex(K key) {
return Math.abs(key.hashCode() % buckets.length);
}
private static class Entry<K, V> {
K key;
V value;
Entry<K, V> next;
Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
}
Hash Implementation Workflow
graph TD
A[Input Key] --> B[Calculate Hash]
B --> C{Bucket Empty?}
C -->|Yes| D[Direct Insert]
C -->|No| E[Handle Collision]
E --> F[Chaining Method]
F --> G[Add to Linked List]
Collision Resolution Techniques
Chaining Implementation
public class CollisionResolutionDemo {
private static class HashNode<K, V> {
K key;
V value;
HashNode<K, V> next;
HashNode(K key, V value) {
this.key = key;
this.value = value;
}
}
public void handleCollision(K key, V value) {
int bucketIndex = getBucketIndex(key);
HashNode<K, V> head = buckets[bucketIndex];
// Chaining collision resolution
while (head != null) {
if (head.key.equals(key)) {
head.value = value;
return;
}
head = head.next;
}
// Insert new node
HashNode<K, V> newNode = new HashNode<>(key, value);
newNode.next = buckets[bucketIndex];
buckets[bucketIndex] = newNode;
}
}
Technique |
Time Complexity |
Space Complexity |
Pros |
Cons |
Chaining |
O(1) average |
O(n) |
Simple implementation |
Potential memory overhead |
Open Addressing |
O(1) average |
O(1) |
Memory efficient |
Linear probing challenges |
Robin Hood Hashing |
O(1) average |
O(1) |
Balanced distribution |
Complex implementation |
Advanced Hash Implementation Patterns
1. Resize and Rehash Strategy
public void resize() {
int newCapacity = buckets.length * 2;
Entry<K, V>[] oldBuckets = buckets;
buckets = new Entry[newCapacity];
size = 0;
for (Entry<K, V> entry : oldBuckets) {
while (entry != null) {
put(entry.key, entry.value);
entry = entry.next;
}
}
}
Best Practices for LabEx Developers
- Implement efficient hash code methods
- Handle edge cases and collisions
- Consider load factor and resizing
- Profile and optimize hash performance
- Use built-in Java hash implementations when possible
By mastering these practical hash implementation techniques, developers can create robust and efficient data structures with LabEx's comprehensive approach to software engineering.