skip to content

Hashtable, IdentityHashMap, WeakHashMap & EnumMap

The maps with a specific job: legacy synchronized Hashtable, IdentityHashMap comparing with ==, WeakHashMap whose keys can be collected, and array-backed EnumMap. Interviewers ask when you would pick one, and each has exactly one good reason.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What is Hashtable, how does it differ from HashMap, and why is it considered a legacy class?

level: juniorimportance: must knowfreq 78%

answer

  1. Every method synchronized -> one big lock
  2. No null key, no null value (NPE)
  3. Java 1.0, extends Dictionary, legacy
  4. Replace with HashMap (single) or ConcurrentHashMap (concurrent)
  5. Enumeration fail-safe; iterator fail-fast

basics

~20 s

Hashtable 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 s

Hashtable 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 lines
java
Hashtable<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

for a junior

Knows Hashtable is thread-safe, rejects nulls, and that HashMap is the usual modern choice.

for a middle

Explains the synchronized-on-every-method mechanism, the null-handling difference, and recommends ConcurrentHashMap for concurrency.

for a senior

Discusses contention cost of the whole-object lock vs ConcurrentHashMap's partitioned locking, fail-fast vs fail-safe traversal, and the Dictionary legacy lineage.

for a principal

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.

context

open as a page

What is EnumMap, how is it implemented, and why is it preferred over HashMap for enum keys?

level: middleimportance: should knowfreq 48%

basics

~20 s

EnumMap is a special map whose keys must be values of one enum type. Internally it's just an array indexed by each enum's position, so it's very fast and compact, and it keeps entries in the enum's declared order.

open as a page

What is IdentityHashMap and how does its notion of key equality differ from a normal HashMap?

level: middleimportance: should knowfreq 45%

basics

~10 s

IdentityHashMap treats two keys as the same only when they are literally the same object (==), not when they are merely equal (.equals()). So two distinct strings with identical text are two different keys.

open as a page

Given Hashtable, IdentityHashMap, WeakHashMap, and EnumMap, how do you decide which specialty map fits a problem?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Pick by the special requirement: EnumMap for enum keys (fast, ordered), WeakHashMap when entries should disappear once keys are unused, IdentityHashMap when keys must match by identity (==), and avoid Hashtable (legacy) — use HashMap or ConcurrentHashMap.

open as a page

What is WeakHashMap, what makes its keys garbage-collectible, and what is a common use for it?

level: seniorimportance: should knowfreq 50%

basics

~20 s

WeakHashMap holds its keys with weak references, so once nothing else points to a key, the garbage collector can remove it and its entry disappears automatically. It's handy for caches that should not keep objects alive.

open as a page