Java中hashCode与equals方法的关系

Relationship between hashCode and equals method in Java

本问题已经有最佳答案,请猛点这里访问。

我在很多地方读过,在Java中重写EDCOX1 0的方法时,也应该重写EDCOX1×1的方法,否则它是"违反合同"。

但到目前为止,如果我只重写equals方法,而不重写hashcode方法,我还没有遇到任何问题。

合同是什么?当我违反合同时,为什么我没有面临任何问题?在哪种情况下,如果我没有重写hashcode方法,我将面临一个问题?


您将遇到的问题是集合,其中元素的唯一性是根据.equals().hashCode()计算的,例如HashMap中的键。

顾名思义,它依赖于哈希表,哈希桶是对象的.hashCode()的函数。

如果有两个对象是.equals(),但具有不同的哈希代码,则会丢失!

合同中最重要的部分是:对象是.equals()必须具有相同的.hashCode()

这一切都记录在JavaDocforObject中。Joshua Bloch说你必须用有效的Java来完成。说得够多了。


根据文档,hashcode的默认实现将返回每个对象不同的整数。

As much as is reasonably practical, the hashCode method defined by class Object does
return distinct integers for distinct objects. (This is typically implemented by
converting the internal address of the object into an integer, but this implementation
technique is not required by the JavaTM programming language.)

但是,有时您希望哈希代码对于具有相同含义的不同对象是相同的。例如

1
2
3
Student s1 = new Student("John", 18);
Student s2 = new Student("John", 18);
s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode

如果在收集框架中使用哈希数据结构(如hashtable、hashset),就会出现这种问题。尤其是对于hashset这样的集合,您将最终拥有重复的元素并违反集合约定。


是的,它应该被覆盖。如果您认为需要覆盖equals(),则需要覆盖hashCode(),反之亦然。hashcode()的一般约定是:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.


  • 见江户记1〔12〕的雅瓦多。

    hashCode()中,它说:

    If two objects are equal according to the equals(Object) method,
    then calling the hashCode method on each of the two objects must
    produce the same integer result.

    (我强调)。

    如果您只覆盖equals(),而不是hashCode(),您的类将违反本合同。

    equals()方法的javadoc中也有这样的说法:

    Note that it is generally necessary to override the hashCode method
    whenever this method is overridden, so as to maintain the general
    contract for the hashCode method, which states that equal objects must
    have equal hash codes.


    合同规定,如果obj1.equals(obj2)那么obj1.hashCode() == obj2.hashCode(),主要是出于性能原因,因为maps主要使用hashcode方法比较条目键。


    约定是:如果两个对象相等,那么它们应该具有相同的哈希代码;如果两个对象不相等,那么它们可能具有相同的哈希代码,也可能不具有相同的哈希代码。

    尝试使用对象作为hashmap中的键(在JoachimSauer的评论后编辑),你将开始面临麻烦。合同是指导方针,不是强加给你的东西。


    看看HashtablesHashmapsHashSets等等。他们都将散列键存储为密钥。当调用get(Object key)时,将生成参数的散列并在给定散列中查找。

    当不重写hashCode()并且密钥的实例已更改(例如,一个根本不重要的简单字符串)时,hashCode()可能会为同一对象生成两个不同的哈希代码,从而导致在map.get()中找不到给定的密钥。