重写equals和hashcode的正确方法是什么,其中两个变量中的任何一个都可以相等?

时间:2016-09-09 02:14:12

标签: java equals hashcode

假设我有以下课程

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方法。

1 个答案:

答案 0 :(得分:6)

不,这是不可能的,因为equals()实现不符合Java API要求:

  

equals方法在非null对象引用上实现等价关系:

     
      
  • reflexive :对于任何非空参考值xx.equals(x)应返回true
  •   
  • 对称:对于任何非空引用值xyx.equals(y)应返回true当且仅当{ {1}}返回y.equals(x)
  •   
  • 传递:对于任何非空引用值truexy,如果z返回{{1} }和x.equals(y)返回true,然后y.equals(z)应该返回true
  •   
  • 一致:对于任何非空引用值x.equals(z)truex的多次调用始终返回y或始终如一返回x.equals(y),前提是没有修改对象true比较中使用的信息。
  •   
  • 对于任何非空引用值falseequals应返回x
  •   

具体而言,它不具有传递性。根据您的定义,x.equals(null)false,但(1,2) == (2,3)

这种非传递性使得无法实现非平凡的哈希码方法。您唯一能做的就是为每个对象返回相同的数字。这是一个有效的实施,但表现很差。