intermediateFree
The equals Without hashCode Trap
Why your HashSet loses the object

Override equals() but not hashCode() and hash-based lookups break - equal objects can land in different buckets.
Watch
The narrated version of this skribble — tap play for the full-size video.
0:00 / 1:23
Deep dive
What You'd Expect
Override equals so two Points with the same x,y are equal, then add one to a HashSet.
- You'd expect
set.contains(new Point(1,2))to find the equal one equals()says they're the same, so the set should agree- Value equality ought to be enough for lookups
What Actually Happens
contains() usually returns false - the set seems to 'lose' the equal object.
- Even though
equals()would say true, the lookup never gets that far - It's unreliable, not always-false: it only 'works' if the buckets happen to collide
- The same bug breaks
HashMapkeys and removal too
Why It Happens
Hash collections find by hashCode first, then equals within a bucket.
- Contract: equal objects MUST return equal hashCodes
- Default
Object.hashCodeis identity-based - different per instance - Different hash → different bucket →
equals()is never even called
The Fix & Best Practice
Always override hashCode whenever you override equals - as a pair.
@Override public int hashCode() { return Objects.hash(x, y); }- Use the SAME fields in
equalsandhashCode - Better: use a
record- it generates consistent equals + hashCode for you



