skip to content

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

level: seniorimportance: should knowfreq 40%

answer

  1. Enum keys -> EnumMap
  2. Die-with-key (GC) -> WeakHashMap
  3. Identity (==) -> IdentityHashMap
  4. Thread-safe -> ConcurrentHashMap, NOT Hashtable
  5. Else -> HashMap (Hashtable is legacy)

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.

solid answer

~40 s

Each specialty map answers a different question. Use EnumMap when keys are constants of one enum type — it's array-indexed by ordinal, faster and smaller than HashMap with deterministic ordering. Use WeakHashMap when you want entries to be garbage-collectible once their keys are no longer strongly referenced elsewhere — typical for non-owning metadata or leak-free caches. Use IdentityHashMap when key matching must be by object identity (==) rather than equals — for object-graph algorithms like serialization, deep copy, and cycle detection. Avoid Hashtable: it's a Java 1.0 legacy class with one coarse synchronized lock and no null support; for single-threaded use HashMap, for concurrency use ConcurrentHashMap. A quick decision: enum keys -> EnumMap; keys should die with their objects -> WeakHashMap; identity semantics -> IdentityHashMap; thread-safe -> ConcurrentHashMap; otherwise -> HashMap.

go deeper

for a junior

Can match each map to a one-line use: enum keys -> EnumMap, GC-able keys -> WeakHashMap, identity -> IdentityHashMap, avoid Hashtable.

for a middle

Explains the deciding requirement behind each choice and why Hashtable is legacy in favor of ConcurrentHashMap/HashMap.

for a senior

Reasons through tradeoffs (ordinal indexing, weak-key GC semantics and leaks, identity-equality correctness, lock granularity) and selects confidently with caveats.

for a principal

Sets team conventions, weighs these against alternatives (Caffeine/soft refs, immutable maps), considers API/maintenance impact, and guides migration off legacy Hashtable in large codebases.

## Why specialty maps exist `HashMap` is the default Java map: any key type, logical (`equals`) matching, no thread-safety, arbitrary iteration order. The four specialty maps each change **one specific dimension** to serve a niche. Choosing well means matching the niche to your actual requirement. ## The decision dimensions Ask these questions in order: ### 1. Are the keys constants of a single enum type? -> EnumMap `EnumMap` is backed by a plain array indexed by each key's `ordinal()` (its position in the enum). No hashing, no collisions, no per-entry node objects — so it's **faster and more memory-compact** than `HashMap`, and it iterates in **enum declaration order** (deterministic). Constraints: keys must all be from the same enum (fixed at construction), null keys are rejected, null values allowed, not thread-safe. **Rule: enum keys -> always prefer EnumMap.** ### 2. Should an entry vanish once its key is no longer used elsewhere? -> WeakHashMap `WeakHashMap` holds **keys via weak references**: if nothing else strongly references a key, the garbage collector can reclaim it and the map drops the entry (lazily, via a `ReferenceQueue`, on later map access). This is for **non-owning associations**: attaching metadata to objects you don't control, or caches that must not keep objects alive (no leak). Gotchas: only keys are weak (a value referencing its key pins the entry), removal timing is non-deterministic, interned strings/cached boxed values never die, not thread-safe. ### 3. Must keys match by *identity* (`==`), not *value* (`equals`)? -> IdentityHashMap Normal maps treat two distinct-but-`equals` objects as one key. `IdentityHashMap` deliberately uses **reference equality (`==`)** and `System.identityHashCode()`, so only the *same instance* is the same key. This is exactly what **object-graph algorithms** need — serialization, deep copy, cycle detection — to track "have I seen *this exact object*?". It's the wrong choice as a general map; keying on value types (String, boxed Integer) causes silent lookup misses. ### 4. Do you need thread-safety? -> ConcurrentHashMap (not Hashtable) `Hashtable` is the Java 1.0 ancestor: thread-safe only via a **single synchronized lock on every method**, so all access is serialized and it doesn't scale; it also rejects null keys/values and extends the obsolete `Dictionary`. It's **legacy** — don't choose it for new code. For concurrency use `ConcurrentHashMap` (fine-grained locking / lock-free reads, scales across cores). If you must fully-synchronize a `HashMap`, `Collections.synchronizedMap` works but still has one coarse lock. ### 5. None of the above? -> HashMap The default. Any keys, `equals`-based matching, fastest general option, allows one null key and null values, not thread-safe. ## Quick reference table | Requirement | Choose | Key matching | Notable trait | |---|---|---|---| | Keys are one enum type | **EnumMap** | ordinal index | fast, compact, ordered, no null key | | Entries should be GC-eligible | **WeakHashMap** | equals (weak keys) | leak-free metadata/caches | | Identity-based keys | **IdentityHashMap** | `==` / identityHashCode | graph/serialization | | Thread-safe | **ConcurrentHashMap** | equals | scalable; (Hashtable is legacy) | | General default | **HashMap** | equals | allows null key/values | ## Common mistakes - Reaching for `Hashtable` for thread-safety (use `ConcurrentHashMap`). - Using `IdentityHashMap` as a general map and hitting phantom lookup misses. - Expecting `WeakHashMap` entries to disappear deterministically, or forgetting a value->key reference pins them. - Using `HashMap<EnumType, V>` when `EnumMap` is strictly better. ## One-line summary Match the map to the *one* special requirement: enum keys -> EnumMap; die-with-key -> WeakHashMap; identity -> IdentityHashMap; thread-safe -> ConcurrentHashMap; else HashMap (and never reach for legacy Hashtable).

  • A teammate uses Hashtable 'because it's thread-safe.' What do you advise?
    Switch to ConcurrentHashMap. Hashtable serializes all access through one lock and won't scale; ConcurrentHashMap uses fine-grained locking and lock-free reads. If they only need a synchronized HashMap, Collections.synchronizedMap exists, but it has the same single-lock limitation as Hashtable.
  • You need to cache computed results keyed by domain objects, but the cache must not cause memory leaks. Which map and what caveat?
    WeakHashMap, so entries become collectible when the keys are no longer used elsewhere. Caveat: only keys are weak, so if a cached value references its key it pins the entry (leak); and timing of removal is non-deterministic. For value-driven eviction, a real cache library is often better.

Choosing a specialty map is like choosing a tool by the one job it's shaped for: a torque wrench (EnumMap, precise+fast for a fixed set), disappearing ink (WeakHashMap, fades when unused), fingerprint lock (IdentityHashMap, identity not name), and an old single-key padlock everyone shares (Hashtable, replaced by the modern multi-lock ConcurrentHashMap).

saying these in an interview costs you the question

  • Recommending Hashtable for new concurrent code.
  • Using IdentityHashMap or WeakHashMap as a general-purpose default map.
  • Picking HashMap for enum keys when EnumMap is strictly better.
  • Assuming any of these (except via wrapping/ConcurrentHashMap) are thread-safe.

context