在两个变量中的任何一个可以相等的情况下,覆盖 equals 和 hashcode 的正确方法是什么?

What is the proper way of overriding equals and hashcode where either of two variables can be equal?

假设我有以下 class

public class DualKey {
    int key1;
    int key2;
    // getters, setters and constructors go here
    public void equals(Object obj) {
        if (obj == null || ! obj instanceOf DualKey)
            return false;
        return this.key1 == obj.key1 || this.key1 == obj.key2 || this.key2 == obj.key1 || this.key2 == obj.key2;
    }

}

是否可以通过保留 equals 和 hashcode 协定的方式覆盖 hashcode?

PS:我意识到定义一个比较器可能会更好,但我正在使用 spark,其中定义相等性的唯一方法是覆盖 equals 方法。

不,不可能,因为equals()实现不符合JavaAPI要求:

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

具体来说,它是不可传递的。根据您的定义,(1,2) == (2,3)(2,3) == (3,4)(1,2) != (3,4).

这种非传递性使得无法实现非平凡的哈希码方法。您唯一可以做的就是 return 每个对象的相同数字。那将是一个有效的实现,尽管性能很差。