Java
equals and hashCode
The contract between them, and the bug you get in a HashMap when you break it.
This is the one piece of the language where overriding a method incorrectly does not throw, does not warn, and silently corrupts a data structure instead.
The contract
Two rules, and only the second one is ever broken by accident.
If two objects are equal, their hash codes must be equal.
If two hash codes are equal, the objects need not be. Different objects are allowed to collide, and hash-based collections expect it.
So the failure mode is always the same shape: you override equals because you
want value comparison, you leave hashCode inherited, and now two objects are
equal with different hashes.
Why that breaks a HashMap
A HashMap finds an entry in two steps. It uses the hash to pick a bucket, then
uses equals to find the right entry inside it.
Skip step one by leaving hashCode alone and the two equal objects land in
different buckets. The map looks in one and never sees the other.
The result is a map where put(k, v) followed by get(k) with an equal key
returns null, which reads as an impossible bug until you know this. Every Java
developer meets it exactly once.
Writing them
@Override
public boolean equals(Object o) {
if (this == o) return
More on this is coming, and asking moves it up the list.
Want this written up?
Sign in and tell us. We write the ones people actually ask for, and asking takes one click.
Sign in to askOr sit with someone on it instead of waiting for us to write it.