Java.Core.🚀 Will Points Be Correctly Placed and Retrieved in a HashSet?

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:

  1. Collisions Happen Unnecessarily
    • Every Point with the same x gets the same hash code, even if y is different.
    • The HashSet puts different Point objects into the same bucket.
  2. 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 different y is already there, equals() returns false, and the object is lost.

Example of Collisions

ObjectxyhashCode()
p1353
p2373

📌 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 both x and y, 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

IssueProblemFix
HashCode Only Uses xDifferent 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 PointsIf 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() Contractequals() 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! 🚀

This entry was posted in Без рубрики. Bookmark the permalink.