Card 06/ 08

GotchaDifficulty: Advanced1 min

Why Changing a Key After Putting It In Loses the Entry

Both methods are overridden correctly, from the same field. The entry goes in, one field on the key object is updated, and the entry is gone.

java
Order key = new Order("AB-1");
Map<Order, String> map = new HashMap<>();
map.put(key, "paid");

key.reference = "AB-2";

System.out.println(map.get(key));
System.out.println(map.get(new Order("AB-1")));
System.out.println(map.size());
text
null
null
1

The bucket was chosen when put ran, from the hash of "AB-1". Changing the field changed the hash and did not move the entry, so the key now hashes to a bucket it is not in — and the old key does not exist any more to hash with.

Put this beside the missing hashCode and the shared fact comes out: the map looked in a bucket the entry is not in, and reported the key as absent rather than failing. One got there by hashing differently from the start; this one got there by hashing differently later. The entry is unreachable either way, and size() still counts it.

Use immutable keys, or keys whose equals and hashCode read only fields that never change. A record with final components is the shape that makes this impossible rather than merely unlikely.