在Java中,对象的hashCode应该改变吗?

In Java, should the hashCode of an object ever change?

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

许多类(如HashSet类)似乎都假定对象的hashCode不会改变。文件清楚说明了equalshashCode之间的关系。

但实现一个在对象生命周期中发生变化的hashCode是不是设计得很差?


在应用程序中至少需要有一个点,在这个点上,哈希代码在一个关注的集合中被冻结。通常,当您构建对象(例如,添加到ArrayList)时,哈希代码将发生更改,然后将其添加到集合中并停止更改。稍后,如果将其从集合中移除,则可以再次对其进行变异。我会说,对于依赖哈希代码的集合(例如,hashmap key或hashset),使用不可变的数据结构(ala string或您自己的类型,总的来说是一个最佳实践。


不,当可变对象更改其内部状态时,哈希代码也可以更改。

但是,一旦对象位于需要常量哈希代码的位置,应用程序必须确保该对象不会发生变化,从而使哈希代码发生变化。


这取决于你所谓的"一生"。您的确切链接表明:

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

这意味着不能保证对象的哈希代码在应用程序的两次不同运行中保持一致。

但它保证在给定的应用程序运行时,这是运行Java代码的JVM的实例,对象的哈希代码永远不会改变。

合同确实保证了这一点,但没有别的。


hashCode不保证同一结果会导致不同的执行。正如javadocs指出的那样-

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.

这是不常见的,类库中的一些类甚至指定了用于计算哈希代码的精确公式——例如字符串。对于这些类,哈希代码总是相同的。但尽管大多数哈希代码实现提供稳定的值,但您不能依赖它。

此外,有些人认为hashCode是对象的唯一句柄。这是错误的,而且是反模式的。例如,字符串"aa"和"bb"产生相同的哈希代码:2112。


你说的是不同的事情。如果要使用Hash(Map|Set),键应该是不可变的对象。所以在这种情况下,哈希代码也是不可变的。但在通常情况下,哈希代码应该随对象状态而更改(根据对哈希代码有意义的字段)。