0

Given following implementation of equals:

public class Test implements Comparable<Test> {
    private int x, y;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Test) {
            Test other = (Test) obj;
            return x == other.x || y == other.y;
        }
        return false;
    }

    @Override
    public int hashCode() {
        //implementation?
    }

    @Override
    public int compareTo(Test o) {
        //implementation?
    }
}

What is correct/most performant implementation of hashCode and compareTo? Please note - equals uses OR, not AND

nerdherd
  • 2,508
  • 2
  • 24
  • 40
Sergey Alaev
  • 3,851
  • 2
  • 20
  • 35
  • 10
    That's not just a "non-standard" equals implementation but an invalid one, as it's not transitive - if `a.x=1`, `a.y=2`, `b.x=3`, `b.y=2`, `c.x=3` and `c.y=4` then `a.equals(b)` and `b.equals(c)` but `a` and `c` are not equal to each other. – Ian Roberts Jun 23 '14 at 17:24
  • Agreed. You are looking for trouble! Also as a general rule equality according to `compareTo` should be identical to equality according to `equals` or you will run into bugs with sorted collections. – Giovanni Botta Jun 23 '14 at 17:27
  • With hashCode the golden rule is that you just have to give a same hashcode value if they are equal, if they are different it doesnt matter.. but its better if its not the same hashcode in that case lol. (to avoid collisions in hashSet or hashMaps) – Ed Morales Jun 23 '14 at 17:28
  • ... though the only `hashCode` implementation that could possibly be consistent with that (flawed) `equals` is the degenerate one that assigns the same hash code to every object. – Ian Roberts Jun 23 '14 at 17:30
  • 1
    See http://stackoverflow.com/questions/7697213/transitive-nature-of-equals-method – Raedwald Jun 25 '14 at 21:55

1 Answers1

4

equals() method is used to determine the equality of two objects.

When we say equality, it should adhere by the following properties,

Reflexive: Always, a = a. In Java, a.equals(a) should always be true.

Symmetric: If a = b, then b = a. In Java, if a.equals(b) is true, then b.equals(a) should be true.

Transitive: If a = b and b = c, then a = c. In Java, if a.equals(b) and b.equals(c) is true, then a.equals(c) should be true.

Your equals() doesnot confront to this rules.

Moreover according to javadoc - It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. So we may face some problem using this implementation of equals() while natural sorting

Good approach for overriding equals method in Java

  1. Do this check -- if yes then return true.
  2. Do null check -- if yes then return false.
  3. Do the instanceof check
  4. Type cast the object
  5. Compare individual attribute starting with numeric attribute because comparing numeric attribute is fast and use short circuit operator for combining checks. If first field does not match, don't try to match rest of attribute and return false.
SparkOn
  • 8,806
  • 4
  • 29
  • 34