NivaarExam PrepOfficial exam papers ↗

25-Comp-B11 Advanced Software Design · December 2014

Question 25 of 26: Java equals/hashCode and HashSet

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

98-Comp-B11 Advanced Software Design — National Exams, December 2014. 3 hours, closed book, no calculator permitted. The paper is organized into five parts, and candidates were instructed to answer any three (3) questions in Part I, any four (4) in Part II, any four (4) in Part III, any two (2) in Part IV, and any two (2) in Part V — only the first questions answered, in each part, as they appear in the answer book are marked. All questions carry equal weight, so the 15 questions actually marked (3+4+4+2+2 of 26) each count for 100/15 ≈ 6.7% of the paper. All 26 questions are answered below for completeness.

Reference texts: Sommerville, Software Engineering (10th ed., Pearson) — software processes, requirements engineering, agile methods, design principles; Pressman, Software Engineering: A Practitioner's Approach (9th ed.) — supplementary process and quality coverage; Gamma, Helm, Johnson & Vlissides (GoF), Design Patterns: Elements of Reusable Object-Oriented Software — structural/behavioural pattern catalogue (Proxy, Bridge, Strategy, Observer, Template Method, Composite, etc.); Sebesta, Concepts of Programming Languages (12th ed.) — polymorphism, dynamic binding, inheritance and language-level object semantics (also underpins the Java/C++ discussion in Part V); Brown, Malveau, McCormick & Mowbray, AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis — anti-pattern catalogue (Question 18). Bertrand Meyer's Object-Oriented Software Construction is cited by name where the paper's own vocabulary (design by contract, open–closed principle) originates there; Barbara Liskov's 1987 substitutability paper is likewise cited by name for Question 11.

PART I — General Principles (answer any 3 of 5)

Question 25: Java equals/hashCode and HashSet (Part V)

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.