25-Comp-B11 Advanced Software Design · December 2014
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.
coll.contains(p2) returns false even though p1.equals(p2) printed true and p1 is literally the element stored in the set, for two compounding reasons.
Root cause 1: the wrong method was overridden. Point declares equals(Point other), not equals(Object other). This does NOT override java.lang.Object.equals(Object) — per Question 7's overloading-vs-overriding distinction, it merely OVERLOADS it, introducing a second, unrelated method that happens to share the name equals but takes a more specific parameter type. HashSet.contains(Object o) internally calls storedElement.equals(o) using the statically-typed Object signature, so it invokes the INHERITED Object.equals(Object) — the one Point never actually overrode — which compares by reference identity. Since p1 and p2 are distinct objects, that comparison is false regardless of their equal x/y fields.
Root cause 2: hashCode was never overridden either. Even setting root cause 1 aside, Java's HashSet is hash-bucket based: contains() first computes o.hashCode() to locate the correct bucket, and only compares candidates WITHIN that bucket via equals(). Point does not override hashCode(), so it inherits Object's identity-based default (derived from the object's memory address) — p1 and p2, being different objects, will almost certainly hash to DIFFERENT buckets, so contains(p2) may never even examine the bucket containing p1.
This demonstrates the equals/hashCode CONTRACT documented on java.lang.Object: objects that are equals()-equal MUST produce equal hashCode()s. Point violates this on both counts, and the violation is silent — the code compiles cleanly and even the first two println calls behave plausibly, so the bug surfaces only at exactly the membership-lookup scenario shown.
Fix. Override both public boolean equals(Object other) (using an instanceof check, a cast, then comparing x/y) AND public int hashCode() (e.g., return Objects.hash(x, y), or an odd-prime combination of x and y on older Java versions) so that any two Points with equal x/y both produce the same hash code and are recognized as equal under the Object-typed overload that HashSet actually calls.