9

I have the following class:

class Point
{
     double x, y;

     // .... constructor and other functions here

     public boolean equals(Point p)
     {
         if(p==null) return(false);
         return(x==p.x && y==p.y);
     }

    public int hashCode()
    {
        int result=17;

        long c1=Double.doubleToLongBits(x);
        long c2=Double.doubleToLongBits(y);

        int ci1=(int)(c1 ^ (c1 >>> 32));
        int ci2=(int)(c2 ^ (c2 >>> 32));

        result = 31 * result + ci1;
        result = 31 * result + ci2;

        return result;
    }
}

Now, if I write the following code:

    Point x=new Point(11,7);
    Point y=new Point(11,7);

    System.out.println("hash-code of x=" + x.hashCode());
    System.out.println("hash-code of y=" + y.hashCode());
    System.out.println("x.equals(y) = " + x.equals(y));
    System.out.println("x==y = " + (x==y));

    java.util.HashSet<Point> s=new java.util.HashSet<Point>();
    s.add(x);
    System.out.println("Contains "+y.toString()+" = "+s.contains(y));
    s.add(y);
    System.out.println("Set size: "+s.size());
    java.util.Iterator<Point> itr=s.iterator();
    while(itr.hasNext()) System.out.println(itr.next().toString());

I am getting the following output:

hash-code of x=79052753
hash-code of y=79052753
x.equals(y) = true
x==y = false
Contains (11.0,7.0) = false
Set size: 2
(11.0,7.0)
(11.0,7.0)

Please help me in understanding why contains() returns false (even after equals() and hashCode() return the same value) and how can I rectify this (i.e. preventing Java from adding duplicate elements). Thanks in advance.

1
  • 2
    Wow! It would be so great If all questions are so clear and understandable, and have code and outputs for reproducing. Well done! Commented Apr 23, 2016 at 5:15

2 Answers 2

8

You have changed the method signature from Object.equals(Object), so you aren't correctly overriding equals. I suggest you use the @Override annotation to catch this class of bugs. Your method should look something like,

@Override
public boolean equals(Object o)
{
     if (this == o) {
         return true;
     }
     if (o instanceof Point) {
         Point p = (Point) o;
         return(x==p.x && y==p.y);
     }
     return false;
}
Sign up to request clarification or add additional context in comments.

1 Comment

I have changed my code and overrode it correctly this time and it solved my problem. Thanks a lot.
7

You are not overriding the equals method in Object.

The signature of equals method is:

public boolean equals(Object obj)

and not

public boolean equals(Point obj)

And please do not compare double values using ==. You should use Double.equals instead.

7 Comments

Value of simple types can be compared using ==
@SergeyMorozov - No. Using == for floating point comparisons is not recommended. It is not safe.
Thanks, it solved my problem. As far as comparison is concerned, according to the documentation, Double.equals returns false when -0.0 and +0.0 are being compared; so I think I would stick to == than Double.equals().
@aetheria - double x = 1.0/3.0; double y = 1 - (2.0/3.0);if (x == y) System.out.println("Equal"); What do you think will the output be?
@user1637645 While I generally agree that one should be careful with floating point comparisons and ==, the delta-based comparison may NOT be used for the implementation of an equals method: The equals method has to be transitive. Consider (only for illustrating the problem) values of x=1, y=2 and z=3. With a delta of 1.5, you will have x.equals(y) and y.equals(z), but x.equals(z) will not hold. This violates the contract of equals.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.