相同的对象不同的哈希码?

时间:2014-07-16 06:59:40

标签: java hashcode

class Rational {
    int num = 0;
    int denom = 0;
    public Rational(int num, int denom) {
        this.num = num;
        this.denom = denom;
    }

public static void main(String[] args) {
    Rational r1 = s.new Rational(1, 1);
    Rational r2 = s.new Rational(1, 1);
    System.out.println(r1.hashCode());
    System.out.println(r2.hashCode());

}

我有两个相同的对象,但它们有不同的hashCode。这是为什么? 我尝试重写Rational中的.equal方法,因此r1.equals(r2)== true。但是他们仍然会产生不同的Java hashCode。

2 个答案:

答案 0 :(得分:4)

它们不是同一个对象;它们是具有相同值的两个不同对象。仅仅因为世界上另一个Jeroen Vannevel并不意味着它就是我。

hashCode()equals()没有关联:他们都有一份他们必须遵守的合同,而且它们是相关的,但它们不会直接影响彼此。这就是为什么你应该总是覆盖这两种方法而不仅仅是一种方法。

答案 1 :(得分:2)

  

我有两个相同的对象

"同样"通常意味着,字面意思是一个对象。您所拥有的是等效的对象。

  

...但他们有不同的hashCode。那是为什么?

因为您没有覆盖hashCode来替换默认实现。覆盖equals不会更改hashCode(如果您覆盖equals,则几乎总是必须覆盖两者。)

hashCode documentation说明Object中的默认实现:

  

尽可能合理,Object类定义的hashCode方法确实为不同的对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但Java™编程语言不需要此实现技术。)

因此,除非您替换hashCode,否则您将为不同的实例获取不同的整数(通常),即使它们是等效的。

在您的情况下,您可以这样做:

@override
public int hashCode() {
    return this.num ^ this.denom;
}

...对hashCode有一个合理的Rational(一定要覆盖equals),但还有很多其他方法。坚持the contract

  

hashCode的一般合约是:

     
      
  • 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
  •   
  • 如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
  •   
  • 如果两个对象根据equals(java.lang.Object)方法不相等则不是必需的,则在两个对象中的每一个上调用hashCode方法必须产生不同的整数结果。但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能。
  •