What is the Difference Between HashMap and Hashtable?
All methods are synchronized:
🟢 Junior Level
HashMap and Hashtable — both store data in “key-value” format, but they are very different classes.
| HashMap | Hashtable |
|---|---|
| Fast | Slow |
| Not thread-safe | Thread-safe |
| Allows null | Forbids null |
| Modern (Java 1.2) | Legacy (Java 1.0) |
Example:
// HashMap — modern choice
Map<String, Integer> map = new HashMap<>();
map.put(null, 1); // OK
map.put("key", null); // OK
// Hashtable — deprecated, don't use
Map<String, Integer> table = new Hashtable<>();
table.put(null, 1); // NullPointerException!
table.put("key", null); // NullPointerException!
Main advice: Always use HashMap (or ConcurrentHashMap for multi-threading). Hashtable is legacy.
🟡 Middle Level
Detailed Comparison
| Characteristic | Hashtable | HashMap |
|---|---|---|
| Synchronization | Yes (every method) | No |
| Null keys | No (NPE) | Yes (1) |
| Null values | No (NPE) | Yes (many) |
| Inheritance | Dictionary | AbstractMap |
| Java version | JDK 1.0 | JDK 1.2 |
| Indexing | hash % n |
(n-1) & hash |
| Iterator | Enumeration + Iterator | Iterator (fail-fast) |
Why is Hashtable Slow?
All methods are synchronized:
public synchronized V put(K key, V value) { ... }
public synchronized V get(Object key) { ... }
Even for reading — a lock is acquired. In a multi-threaded environment, all threads queue up.
Indexing Algorithm
HashMap: (n-1) & hash — fast bitwise mask (requires power of two)
Hashtable: (hash & 0x7FFFFFFF) % n — modulo division (slower, but works with any size)
HashMap additionally spreads the hash via a spread function (XOR of high and low 16 bits) for better distribution. Hashtable takes hashCode() directly.
Where Is Hashtable Still Found?
- Legacy code (projects older than 15-20 years)
- Interview questions 😊
- Textbooks that haven’t been updated
What to Use Instead?
| Need | Use Instead of Hashtable |
|---|---|
| Simple Map | HashMap |
| Thread safety | ConcurrentHashMap |
| Synchronized Map | Collections.synchronizedMap(new HashMap<>()) |
Common Mistakes
- Using Hashtable in new code — this is an anti-pattern
- Thinking Hashtable = fast ConcurrentHashMap — no, it’s slower
- Enumeration vs Iterator — Hashtable returns Enumeration (no remove, no fail-fast)
🔴 Senior Level
Internal: Synchronization Overhead
Each synchronized method — monitor enter/exit:
// Hashtable.put:
public synchronized V put(K key, V value) {
// monitor enter
// ... logic
// monitor exit
}
In a multi-threaded environment:
- Contention on a single monitor
- Thread parking/unparking
- Memory barrier on every enter/exit
ConcurrentHashMap solves this via CAS + granular locking.
Historical Context
- Dictionary (1995) — abstract ancestor of Hashtable, deprecated
- Hashtable (1995) — adapted to Map in Java 1.2
- HashMap (1998) — created from scratch for Collections Framework
Hashtable was kept only for backward compatibility.
Indexing: Modulo vs Bitwise AND
// Hashtable:
int index = (hash & 0x7FFFFFFF) % table.length;
// & 0x7FFFFFFF — removes the sign bit (hash can be negative)
// % — modulo division, expensive operation
// HashMap:
int index = (n - 1) & hash;
// Only when n = 2^k
// & — bitwise AND, 1 cycle
Hashtable can use prime numbers for table size (better distribution), but modulo is more expensive.
Thread Safety: Hashtable vs ConcurrentHashMap
| Metric | Hashtable | ConcurrentHashMap |
|---|---|---|
| Read (1 thread) | ~15 ns | ~8 ns |
| Read (8 threads) | ~500 ns | ~60 ns |
| Write (1 thread) | ~20 ns | ~15 ns |
| Write (8 threads) | ~2000 ns | ~120 ns |
Hashtable loses 10-30x on multi-threaded operations.
Why Hashtable is Still in JDK
- Backward compatibility (millions of lines of legacy code)
- Some enterprise frameworks depend on it
- Removing it would break code (even if it’s bad)
Modern Best Practice
// Never:
Map<K, V> map = new Hashtable<>();
// Instead:
Map<K, V> map = new HashMap<>(); // Single-thread
Map<K, V> map = new ConcurrentHashMap<>(); // Multi-thread
Map<K, V> map = Collections.synchronizedMap(new HashMap<>()); // If full synchronization needed
🎯 Interview Cheat Sheet
Must know:
- Hashtable — legacy (Java 1.0), HashMap — modern choice (Java 1.2)
- Hashtable is synchronized (every method) → slow, HashMap — not
- Hashtable forbids null, HashMap allows null key and null values
- Indexing: Hashtable =
(hash & 0x7FFFFFFF) % n, HashMap =(n-1) & hash - HashMap uses spread function (XOR high/low 16 bits), Hashtable takes hashCode() directly
- Hashtable loses 10-30x to ConcurrentHashMap on multi-threaded operations
- Hashtable kept only for backward compatibility
Common follow-up questions:
- When to use Hashtable? — never in new code; only legacy support
- Why is Hashtable slower than ConcurrentHashMap? — single monitor for everything vs granular locking + CAS
- How does Enumeration differ from Iterator? — Enumeration has no remove() and no fail-fast
- Why is HashMap faster? — bitwise mask
&vs division%, no synchronization
Red flags (DO NOT say):
- “Hashtable = fast thread-safe Map” — no, slower than ConcurrentHashMap
- “HashMap uses division for indexing” — no, bitwise mask
- “You can use Hashtable in new code” — no, it’s an anti-pattern
Related topics:
- [[23. What is ConcurrentHashMap and How Does It Differ from HashMap]]
- [[22. How HashMap Works in a Multi-threaded Environment]]
- [[01. How HashMap Works Internally]]