Hashtable vs ConcurrentHashMap in Java: A Deep Dive
In Java, working with key-value pairs efficiently is essential for building scalable and thread-safe applications. Two commonly discussed classes in this realm are Hashtable and ConcurrentHashMap. Though both are designed to work in multi-threaded environments, they differ significantly in design, performance, and behavior.
In this blog post, we'll explore these two classes in depth, understand their key differences, use cases, and make an informed decision on when to use which.
1. Introduction to Hashtable
What is Hashtable?
Hashtable
is a legacy class in Java that implements the Map
interface and provides a thread-safe way to store key-value pairs. It was part of the original version of Java, even before the Collections framework was introduced in Java 1.2.
Key Characteristics:
-
Synchronized methods for thread safety.
-
Does not allow
null
keys ornull
values. -
Slower performance due to method-level synchronization.
-
Iterators are fail-fast and throw
ConcurrentModificationException
if modified concurrently.
Example Usage:
import java.util.Hashtable;
public class HashtableExample {
public static void main(String[] args) {
Hashtable<Integer, String> table = new Hashtable<>();
table.put(1, "Apple");
table.put(2, "Banana");
System.out.println("Value for key 1: " + table.get(1));
}
}
2. Introduction to ConcurrentHashMap
What is ConcurrentHashMap?
Introduced in Java 5 as part of the java.util.concurrent
package, ConcurrentHashMap
is designed to offer highly scalable and thread-safe operations without locking the entire map.
Key Characteristics:
-
Implements
ConcurrentMap
andMap
interfaces. -
Allows concurrent read and concurrent write with minimal locking.
-
Allows
null
values neither as key nor as value. -
Uses bucket-level locking (Segmented locking) or CAS-based techniques (depending on Java version).
-
Iterators are weakly consistent — they reflect some, but not necessarily all, updates.
Example Usage:
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>();
map.put(1, "Red");
map.put(2, "Blue");
System.out.println("Value for key 2: " + map.get(2));
}
}
3. Key Differences Between Hashtable and ConcurrentHashMap
Feature | Hashtable | ConcurrentHashMap |
---|---|---|
Thread Safety | Thread-safe via synchronized methods | Thread-safe via fine-grained locking |
Performance | Poor in high concurrency due to global lock | Superior due to segmented locking |
Null Keys/Values | Neither key nor value can be null | Same – neither key nor value can be null |
Iterator | Fail-fast | Weakly consistent |
Lock Granularity | Locks entire map for every operation | Locks at bucket level or per segment |
Legacy vs Modern | Legacy class, part of Java 1.0 | Modern, introduced in Java 5 |
Usage in New Code | Discouraged | Recommended for concurrent scenarios |
Why null
is Not Allowed?
Neither Hashtable
nor ConcurrentHashMap
allow null
keys or values. Why?
-
Hashtable: This design is historical.
-
ConcurrentHashMap: The main reason is to avoid ambiguity — a
null
return fromget(key)
could mean either the key is absent or explicitly mapped tonull
.
↔ Thread Safety: How Do They Differ?
Hashtable:
public synchronized V put(K key, V value) {
// synchronized on the entire table
}
-
Every operation is synchronized on the entire map.
-
Causes contention and reduced performance in multithreaded applications.
ConcurrentHashMap:
-
Uses bucket-level locking (Java 7 and earlier).
-
Uses lock-free reads and CAS (Compare-And-Swap) in Java 8 and above.
-
Multiple threads can read and write concurrently without blocking each other unnecessarily.
Performance Comparison
Hashtable:
-
Locking entire map for each operation results in serialization of threads.
-
Suitable only for very small datasets or when minimal concurrency is expected.
ConcurrentHashMap:
-
Designed for high concurrency.
-
Efficient for both read and write operations in multi-threaded environments.
-
Often used in real-time data processing applications, caching, and distributed systems.
Code Example: Comparing Thread Performance
import java.util.Hashtable;
import java.util.concurrent.*;
public class MapPerformanceTest {
public static void main(String[] args) throws InterruptedException {
Hashtable<Integer, Integer> hashtable = new Hashtable<>();
ConcurrentHashMap<Integer, Integer> concurrentMap = new ConcurrentHashMap<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
Runnable hashtableTask = () -> {
for (int i = 0; i < 1000; i++) {
hashtable.put(i, i);
}
};
Runnable concurrentMapTask = () -> {
for (int i = 0; i < 1000; i++) {
concurrentMap.put(i, i);
}
};
long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) executor.execute(hashtableTask);
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
long end = System.currentTimeMillis();
System.out.println("Hashtable time: " + (end - start) + " ms");
executor = Executors.newFixedThreadPool(10);
start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) executor.execute(concurrentMapTask);
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
end = System.currentTimeMillis();
System.out.println("ConcurrentHashMap time: " + (end - start) + " ms");
}
}
When Should You Use What?
Use ConcurrentHashMap when:
-
You are developing high-performance, multi-threaded applications.
-
Your application has frequent concurrent reads/writes.
-
You are building scalable APIs or real-time data pipelines.
Avoid Hashtable unless:
-
You are maintaining legacy code.
-
You specifically need the synchronized behavior and can't use newer alternatives.
-
No concurrency is involved and thread safety is not critical.
Conclusion
Although both Hashtable
and ConcurrentHashMap
are thread-safe, their internal implementations and performance differ drastically. ConcurrentHashMap
is the go-to choice for modern concurrent applications due to its non-blocking algorithms and superior throughput under load.
Use Case | Recommendation |
---|---|
High-performance concurrent access | ConcurrentHashMap |
Legacy application maintenance | Hashtable (with caution) |
Null key/value support needed | Neither (use HashMap if thread safety isn’t required) |
Sign up here with your email
ConversionConversion EmoticonEmoticon