No, the points will not be correctly handled in a HashSet
.
The issue is that hashCode()
only uses x
, while equals()
compares both x
and y
.
This violates the contract between equals()
and hashCode()
.
1️⃣ Understanding the Problem
Incorrect Point
Class
import java.util.HashSet;
import java.util.Set;
class Point {
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Point point = (Point) obj;
return this.x == point.x && this.y == point.y; // ✅ Compares x and y
}
@Override
public int hashCode() {
return x; // ❌ Only considers x, ignoring y
}
}
public class Main {
public static void main(String[] args) {
Set<Point> set = new HashSet<>();
Point p1 = new Point(3, 5);
Point p2 = new Point(3, 7); // Same x but different y
set.add(p1);
set.add(p2);
System.out.println(set.contains(new Point(3, 5))); // ✅ True
System.out.println(set.contains(new Point(3, 7))); // ❌ False (Wrong behavior)
System.out.println(set.size()); // ❌ Expected: 2, but might be 1 (incorrect behavior)
}
}
2️⃣ Why Is This Wrong?
The hashCode()
method only uses x
, while equals()
compares both x
and y
.
This means:
- Collisions Happen Unnecessarily
- Every
Point
with the samex
gets the same hash code, even ify
is different. - The
HashSet
puts differentPoint
objects into the same bucket.
- Every
HashSet
May Not Store Objects Properly- When checking
set.contains(p2)
, Java:- Finds the bucket based on
hashCode()
. - Iterates through the bucket using
equals()
. - If an object with the same
x
but differenty
is already there,equals()
returnsfalse
, and the object is lost.
- Finds the bucket based on
- When checking
Example of Collisions
Object | x | y | hashCode() |
---|---|---|---|
p1 | 3 | 5 | 3 |
p2 | 3 | 7 | 3 |
📌 Since p1
and p2
have the same hash code (3
), they go into the same bucket.
If p1
is stored first, adding p2
fails because equals()
says they are different, and the HashSet
may discard p2
or fail to retrieve it later.
3️⃣ How to Fix It?
We must ensure that equal objects (equals() == true
) always have the same hash code by including both x
and y
in hashCode()
.
✅ Fixed Point
Class
import java.util.Objects;
class Point {
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Point point = (Point) obj;
return this.x == point.x && this.y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y); // ✅ Includes both x and y
}
}
🔹 Why Does This Work?
hashCode()
now considers bothx
andy
, ensuring that equal objects have the same hash code.HashSet
can now correctly store and retrieve points.
4️⃣ Verifying the Fix
public class Main {
public static void main(String[] args) {
Set<Point> set = new HashSet<>();
Point p1 = new Point(3, 5);
Point p2 = new Point(3, 7);
set.add(p1);
set.add(p2);
System.out.println(set.contains(new Point(3, 5))); // ✅ True
System.out.println(set.contains(new Point(3, 7))); // ✅ True
System.out.println(set.size()); // ✅ Correctly prints 2
}
}
Now, the HashSet
stores both points correctly.
📌 Summary
Issue | Problem | Fix |
---|---|---|
HashCode Only Uses x | Different Point objects with the same x have the same hash code, leading to collisions. | Use Objects.hash(x, y) to consider both fields. |
HashSet Fails to Store/Retrieve Some Points | If two points have the same x but different y , they are placed in the same bucket and might be discarded. | Ensure hashCode() includes all fields used in equals() . |
Violates the equals() –hashCode() Contract | equals() uses x and y , but hashCode() only uses x , causing incorrect behavior in hash-based collections. | Follow the contract: equal objects must have the same hash code. |
✅ Final Best Practices
✔ Always override hashCode()
when overriding equals()
.
✔ Use Objects.hash(x, y)
to generate a proper hash code.
✔ Ensure hashCode()
includes the same fields as equals()
.
✔ Test your class in HashSet
and HashMap
to verify correctness.
By following these rules, your Point
class will work correctly and efficiently in Java collections! 🚀