Question 28 · Section 13

What happens if you modify a mutable key in HashMap?

If you modify an object used as a key in HashMap, it gets lost — you won't be able to find it.

Language versions: English Russian Ukrainian

Junior Level

If you modify an object used as a key in HashMap, it gets lost — you won’t be able to find it.

List<String> key = new ArrayList<>(List.of("A"));
Map<List<String>, String> map = new HashMap<>();
map.put(key, "value");

key.add("B"); // Modified the key!
System.out.println(map.get(key)); // null — not found!

Why

  • On put, HashMap computed the hash of ["A"] → placed in bucket #5
  • After key modification, hash of ["A", "B"] → different bucket
  • get searches in the wrong bucket → null

The object is still in the map, but you can’t retrieve it.


Middle Level

Failure mechanics

  1. put(key, value) — key hash → bucket #5
  2. Mutation — changed a key field → new hash
  3. get(key) — new hash → bucket #10 → empty → null

The object is physically still in bucket #5, but became unreachable.

Consequences

Logical unreachability: the object cannot be retrieved via get() or removed via remove() using the modified key. It occupies space until the entire map is cleared or entrySet() is iterated.

Duplicates in HashSet:

Set<List<String>> set = new HashSet<>();
set.add(new ArrayList<>(List.of("A")));
// Modified an element inside the list
set.add(new ArrayList<>(List.of("A"))); // Added again!

How to find the lost object

Through full iteration — O(n) instead of O(1):

for (var entry : map.entrySet()) {
    if (entry.getKey().contains("A")) {
        // found it
    }
}

Senior Level

How to avoid

  1. Immutable keysString, UUID, Record — always
  2. Remove → modify → add:
    V value = map.remove(key);
    key.mutate();
    map.put(key, value);
    
  3. IdentityHashMap — if mutation is inevitable and you don’t control the object (comparison by ==)
    Map<List<String>, String> map = new IdentityHashMap<>();
    // Comparison by ==, not equals — mutation doesn't break lookup as long as it's the same object.
    

The deep problem

Modifying a mutable key breaks the HashMap invariant: the key’s hashCode must be stable. This is not a HashMap bug, but a violation of the hashCode() contract — if equals hasn’t changed, then hashCode should be the same, but mutation changes both.

Summary for Senior

  • Modifying a mutable key “breaks” the map — object is unreachable via get()
  • This is a classic memory leak and source of hard-to-find bugs
  • Always design keys as immutable entities
  • If mutation is necessary: removemutateput
  • IdentityHashMap — a last resort when key control is impossible

Interview Cheat Sheet

Must know:

  • Mutable key modification → new hashCode → get searches in a different bucket → null
  • Object is physically in the map, but became unreachable — logical memory leak
  • Duplicates in HashSet: modified object is added again as “new”
  • Lost object can only be found via entrySet iteration — O(n) instead of O(1)
  • How to avoid: immutable keys always, or remove → mutate → put
  • IdentityHashMap — compares by ==, mutation doesn’t break lookup (as long as it’s the same object)

Frequent follow-up questions:

  • Is the object removed from the map? — No, it stays in the old bucket, but is unreachable via get/remove
  • How to find a lost object? — Iterate entrySet — O(n)
  • Does IdentityHashMap solve the problem? — Yes, compares by reference, but it’s a specific use case
  • Is this a HashMap bug? — No, it’s a contract violation: hashCode must be stable

Red flags (do NOT say):

  • “The object is removed from the map” — no, it stays but is unreachable
  • “HashMap fixes the hashCode itself” — no, it’s the developer’s contract
  • “Mutable key is fine” — classic source of memory leaks and bugs
  • “IdentityHashMap is a replacement for HashMap” — it’s a completely different structure, compares by reference

Related topics:

  • [[27. Can you use immutable objects as keys in HashMap]]
  • [[22. What are the advantages of immutable objects for caching]]
  • [[20. What is Record and how does it help create immutable classes]]
  • [[14. What is the difference between shallow copy and deep copy]]