What is the difference between HashMap, Hashtable, and ConcurrentHashMap?

9 minintermediatehashmaphashtableconcurrenthashmap

Quick Answer

HashMap is unsynchronized and allows one null key plus null values — fast but not thread-safe. Hashtable is a legacy, fully synchronized (method-level locking) map that disallows null keys/values — thread-safe but slow under contention. ConcurrentHashMap is thread-safe using fine-grained internal locking/CAS (not a single lock), offering much better concurrent throughput than Hashtable while also disallowing null keys/values.

Detailed Answer

HashMapHashtableConcurrentHashMap
Thread safetynonefully synchronized (every method locks)thread-safe, fine-grained (no single global lock)
Null keys/values1 null key, many null valuesnone allowednone allowed
Performance under concurrencyfastest, single-threaded useslow — one thread at a time, even for readshigh — concurrent reads, striped/CAS-based writes
Iterationfail-fast (ConcurrentModificationException)fail-fastweakly consistent (never throws CME, may or may not reflect concurrent updates)
Eramodern defaultlegacy (pre-Java 2 collections, Map interface retrofitted on)java.util.concurrent, the modern concurrent choice

Hashtable is effectively deprecated in practice — it predates the Collections Framework and synchronizes every single method call (get, put, size, ...), which serializes all access even for read-heavy workloads.

ConcurrentHashMap achieves thread safety without that bottleneck: historically via segment-level locking, and since Java 8 via per-bucket synchronization plus CAS operations on individual bins, so unrelated keys rarely contend. Its null restriction is deliberate: in a concurrent map, map.get(key) == null can't distinguish "no such key" from "key maps to null" reliably when another thread might be concurrently modifying the map — Doug Lea (its author) chose to simply disallow nulls entirely.

Rule of thumb: use HashMap single-threaded (or externally synchronized if needed), and ConcurrentHashMap for shared, concurrent access. Avoid Hashtable in new code entirely.