Challenge 2: equals() Without hashCode() Breaking a HashSet — Possible Solution ==================================================================== Broken attempt — BrokenPoint.java: import java.util.HashSet; import java.util.Set; public class BrokenPoint { private int x, y; public BrokenPoint(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (!(o instanceof BrokenPoint p)) return false; return x == p.x && y == p.y; } // no hashCode() override -- still uses Object's identity-based default public static void main(String[] args) { Set points = new HashSet<>(); points.add(new BrokenPoint(1, 2)); points.add(new BrokenPoint(1, 2)); // "equal" per equals(), but... System.out.println("Broken set size: " + points.size()); } } Output: Broken set size: 2 Explanation: Both BrokenPoint instances are equal() to each other, but each one's inherited, identity-based hashCode() is different, since they're two distinct objects in memory. HashSet checks hashCode() first to decide which bucket to look in -- since the two objects hash differently, the second add() never even compares them with equals(); it just adds a second, distinct entry into a different bucket. Fixed — GoodPoint.java: import java.util.HashSet; import java.util.Objects; import java.util.Set; public class GoodPoint { private int x, y; public GoodPoint(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (!(o instanceof GoodPoint p)) return false; return x == p.x && y == p.y; } @Override public int hashCode() { return Objects.hash(x, y); } public static void main(String[] args) { Set points = new HashSet<>(); points.add(new GoodPoint(1, 2)); points.add(new GoodPoint(1, 2)); System.out.println("Fixed set size: " + points.size()); } } Output: Fixed set size: 1 WHY THIS WORKS AS AN ANSWER ------------------------------ This reproduces the exact broken-contract scenario the chapter warns about -- equals() overridden alone -- showing the HashSet silently accepting two "equal" elements, then fixes it precisely the way the chapter's tip-box recommends: adding a matching hashCode() override.