Card 07/ 08

ExerciseDifficulty: Advanced1 min

Practice: Which Classes Are Safe as HashMap Keys

No overrides, equals alone, a record, and a mutable field: which can you look up by value.

A safe key overrides equals and hashCode together, from fields that never change; without overrides, a key matches only the very same object. For each of the four classes below, decide whether it can be used as a HashMap key without losing entries, all four before opening the answer.

java
// 1
class A { final String id; }

// 2
class B { final String id;
    @Override public boolean equals(Object o) { /* compares id */ }
}

// 3
record C(String id, long pence) { }

// 4
class D { String id;
    @Override public boolean equals(Object o) { /* compares id */ }
    @Override public int hashCode() { return Objects.hash(id); }
}
Which of the four are safe, and what goes wrong in the others?
Each class, whether it is safe as a key, and why
ClassSafe?Why
AYes, but only as identityNeither method overridden, so a key works only if you keep the very same object
BNoequals without hashCode: two equal keys usually land in different buckets, the slots a map sorts keys into
CYesA record supplies both from its components, and they are final
DNoBoth overridden correctly, and id is not final: changing it strands the entry

A is the interesting answer. It is not broken: it behaves exactly as intended, and what it means by a key is "this particular object". That is right for something like a cache keyed on an instance, and wrong for anything you will look up by value.

D is the one people miss, because it looks like the correct version. Correct methods reading a mutable field is the same bug arriving later.