What is Hashtable, how does it differ from HashMap, and why is it considered a legacy class?
answer
- Every method synchronized -> one big lock
- No null key, no null value (NPE)
- Java 1.0, extends Dictionary, legacy
- Replace with HashMap (single) or ConcurrentHashMap (concurrent)
- Enumeration fail-safe; iterator fail-fast
basics
~20 sHashtable is an old key-value map that is thread-safe because every method is synchronized, and it refuses null keys and null values. HashMap is newer, faster, allows one null key and null values, but is not thread-safe.
solid answer
~40 sHashtable is a legacy map from Java 1.0 that stores key-value pairs. Every public method is synchronized on the table object, so it is thread-safe but slow under contention because only one thread can touch it at a time. It rejects null keys and null values, throwing NullPointerException. HashMap (Java 1.2) is the modern replacement: not synchronized, faster, and it permits one null key plus null values. Both compute a bucket from the key's hashCode and resolve collisions, and both implement Map, but Hashtable also extends the obsolete Dictionary class and its Enumeration is fail-safe rather than fail-fast (its iterator is fail-fast). For single-threaded code use HashMap; for concurrent code prefer ConcurrentHashMap, which locks only parts of the table and scales far better than Hashtable's whole-object lock.
code
java · 11 linesHashtable<String, String> ht = new Hashtable<>();
ht.put("a", "1"); // ok
// ht.put(null, "x"); // throws NullPointerException
// ht.put("k", null); // throws NullPointerException
HashMap<String, String> hm = new HashMap<>();
hm.put(null, null); // perfectly fine in HashMap
// Prefer this for concurrency, not Hashtable:
ConcurrentHashMap<String, String> chm = new ConcurrentHashMap<>();
chm.put("a", "1");go deeper
Knows Hashtable is thread-safe, rejects nulls, and that HashMap is the usual modern choice.
Explains the synchronized-on-every-method mechanism, the null-handling difference, and recommends ConcurrentHashMap for concurrency.
Discusses contention cost of the whole-object lock vs ConcurrentHashMap's partitioned locking, fail-fast vs fail-safe traversal, and the Dictionary legacy lineage.
Frames Hashtable as a cautionary design (coarse locking), reasons about when synchronizedMap vs ConcurrentHashMap is appropriate, memory-visibility guarantees, and migration strategy for legacy codebases.
## What a Map is A **Map** is a data structure that stores **key-value pairs**: you give it a key (like a word) and it gives you back a value (like that word's definition). Each key appears at most once. Java's `java.util.Map` interface defines this contract (`put`, `get`, `remove`, etc.). ## What hashing means here Most maps are **hash-based**: when you `put(key, value)`, the map calls `key.hashCode()` to get an integer, then maps that integer to a slot (a **bucket**) in an internal array. `get(key)` repeats the calculation to jump straight to the right bucket. When two keys land in the same bucket (a **collision**), the entries are chained together and compared with `equals()`. This is what makes `get`/`put` average **O(1)** (constant time). ## Hashtable `Hashtable` is one of Java's original classes (Java 1.0, 1996). It is a hash-based map with two defining traits: 1. **Every method is `synchronized`.** `synchronized` means the JVM forces a thread to acquire a lock (the table object's monitor) before running the method, and only one thread can hold that lock at a time. So `Hashtable` is **thread-safe**: multiple threads can call it without corrupting it. The cost is **contention** — even readers must wait their turn, so it does not scale on multi-core machines. 2. **It forbids `null`.** Passing a null key or null value throws `NullPointerException`. (Historically because a null return from `get` would be ambiguous, and because it used the key's `hashCode`, which a null has none of.) `Hashtable` also extends the abandoned `Dictionary` class and predates the Collections Framework, so it carries `Enumeration`-based traversal as well as the modern `Iterator`. ## HashMap — the modern replacement `HashMap` (Java 1.2, part of the Collections Framework) is the everyday map. Differences: | | Hashtable | HashMap | |---|---|---| | Thread-safe | Yes (every method synchronized) | No | | null key | No (NPE) | One allowed | | null values | No (NPE) | Allowed | | Speed (single thread) | Slower (lock overhead) | Faster | | Legacy / Dictionary | Yes | No | | Traversal | Enumeration (fail-safe) + Iterator (fail-fast) | Iterator (fail-fast) | **Fail-fast** means an iterator throws `ConcurrentModificationException` if the map is structurally changed while you iterate (it detects this via a modification counter). Hashtable's older `Enumeration` does **not** do this. ## What to use instead - **Single-threaded:** use `HashMap`. - **Concurrent:** do **not** use `Hashtable`. Use `ConcurrentHashMap`, which partitions the table and locks only small portions (or uses lock-free reads), so many threads proceed in parallel. If you genuinely need a fully-synchronized `HashMap`, wrap it with `Collections.synchronizedMap(new HashMap<>())` — but that still has one big lock, like Hashtable. ## Why "legacy" `Hashtable` is retired in practice: it survives only for backward compatibility. Its whole-object lock is a poor concurrency design, and its null prohibition is a frequent surprise. Modern code uses `HashMap` or `ConcurrentHashMap`.
- Why does Hashtable reject null keys and values while HashMap allows them?Hashtable was designed before null-handling conventions settled; a null value would make get() ambiguous (null could mean absent or present-with-null), and it called hashCode() directly on keys. HashMap handles a null key specially (bucket 0) and uses containsKey() to disambiguate null values.
- If I need a thread-safe map today, what should I use instead of Hashtable?ConcurrentHashMap, which uses fine-grained locking / lock-free reads and scales across cores. Collections.synchronizedMap is an option but uses a single lock like Hashtable, so it does not scale better.
Hashtable is a shop with one cashier and a rule that turns away anyone without a name tag (no nulls). HashMap drops the cashier (faster, but no theft protection); ConcurrentHashMap opens many checkout lanes (scales).
saying these in an interview costs you the question
- Saying Hashtable allows a null key like HashMap does (it throws NPE).
- Claiming Hashtable is a good choice for modern concurrent code (use ConcurrentHashMap).
- Thinking 'synchronized methods' means it scales well under many threads — it serializes all access.
- Confusing fail-fast iterators with fail-safe Enumeration.