Hashtable : Deep Deep Explanation
Hashtable is one of the oldest collection classes in the Java ecosystem, dating back to JDK 1.0. Found in the java.util package, it is a legacy data structure that maps keys to values, very similar to a HashMap. But it possesses one critical, defining difference: It is fully synchronized (thread-safe).
table.put(101, "A");
table.put(102, "B");
System.out.println(table);
// Output: {102=B, 101=A} (No guaranteed order)
1. Internal Architecture & Node Structure
Like HashMap, Hashtable uses a Hash Table internally. This means it relies on an array of "buckets," and each bucket handles collisions by forming a linked list of nodes.
Hierarchy: Object → Dictionary (Legacy) → Hashtable.
The Node Structure
Every key-value pair is wrapped in this Entry object. It holds the cached hash, the key, the value, and a next pointer to handle separate chaining (collisions).
2. Backend Working Step-by-Step: put() & get()
Let's trace the exact backend flow when you run: table.put(15, "Java");
- STEP 1 — Hash Calculation: Java triggers
key.hashCode(). For an integer like 15, the hash is exactly15. - STEP 2 — Bucket Index Math: To map the hash to a specific array bucket, Java uses a slightly different formula than HashMap to ensure positive integers:
$$ \text{index} = (\text{hash} \ \& \ \text{0x7FFFFFFF}) \pmod{\text{table.length}} $$
If the table length is11, then15 % 11 = 4. The entry maps to bucket 4. - STEP 3 — Insert Node: An
Entry[15, Java]is physically placed inside bucket 4.
The Golden Rule of equals() & hashCode()
If you use a custom object (like a Student class) as a key, you MUST override hashCode() and equals(). Why? Because the default Object methods compare memory addresses. If you insert a value with new Student(1), and later try to retrieve it using a separate new Student(1), the memory addresses won't match, and Hashtable will return null.
3. Synchronization: The Ultimate Bottleneck
The single most important concept regarding Hashtable is its synchronization. Every core method in the class is marked with the synchronized keyword:
This means Java enforces an Object Monitor Lock on the entire Hashtable instance.
Why does this make Hashtable extremely slow?
Because it suffers from severe Thread Contention. Even if Thread 1 is updating bucket 2, and Thread 2 just wants to read data from bucket 8, Thread 2 is completely blocked. The entire data structure freezes for a single operation.
4. Resizing, Rehashing & Null Rules
Like all hash tables, when the structure gets too full, performance degrades. To fix this, Java automatically resizes it.
- Load Factor: Defaults to
0.75. - Threshold calculation:
Capacity × Load Factor. (e.g., $11 \times 0.75 = 8$). At the 8th insertion, the table resizes. - The Resize Formula: Unlike HashMap which perfectly doubles, Hashtable uses: $ (\text{oldCapacity} \times 2) + 1 $. (e.g., 11 becomes 23).
- Rehashing: A new, larger array is created. Every single existing node is recalculated and moved. This is a massively expensive operation.
The Null Handling Crash
Hashtable absolutely DOES NOT allow null keys or null values.
Why? Because internally, the very first step in put() is to execute key.hashCode(). Invoking a method on a null reference immediately triggers a hard NPE crash.
5. Hashtable vs. The Modern Alternatives
Modern Java architectures rarely use Hashtable. Here is why it was replaced:
| Feature | HashMap (Fast) | Hashtable (Legacy) |
|---|---|---|
| Thread-Safe | No | Yes |
| Speed | Very Fast | Slow (Bottlenecked) |
| Null Keys | 1 Allowed | Not Allowed (NPE) |
| Null Values | Multiple Allowed | Not Allowed (NPE) |
| Feature | ConcurrentHashMap (Modern Solution) | Hashtable (Legacy Solution) |
|---|---|---|
| Locking Strategy | Locks only individual buckets (Node level) | Locks the entire Object |
| Read Operations | Fully concurrent (No locking needed) | Blocked while writing is happening |
| Performance in Multi-threading | Extremely High | Extremely Poor |
The Real-Life Analogy & Summary
Think of a Hashtable like a giant room full of apartment lockers protected by a single, highly strict security guard.
- Safe? Yes. The guard only allows exactly ONE person inside the entire room at a time. No one will ever bump into each other.
- Fast? Absolutely not. If you want to check Locker #5, and someone else is putting a package in Locker #99, you must wait outside in the rain until they are completely finished.
Why does it still exist? Purely for backward compatibility with ancient Java codebases (JDK 1.0/1.1) and legacy APIs. For any modern application requiring thread safety, you should immediately reach for ConcurrentHashMap instead.
Comments
Post a Comment