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

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

似乎很多类(例如HashSet)假设一个对象的hashCode不会改变。 documentation 很清楚 equalshashCode 之间的关系应该是什么。

但是实现在对象的整个生命周期中发生变化的 hashCode 是不是糟糕的设计?

不,当一个可变对象改变它的内部状态时 hashCode 改变是可以的。

但是,一旦对象位于需要常量 hashCode 的地方,应用程序就必须确保对象不会发生突变,从而使 hashCode 发生变化。

应用程序中至少需要指出 hashCode 在关心的集合中时被冻结的地方。通常,hashCode 会在您构建对象(例如,添加到 ArrayList)时更改,然后将其添加到集合并停止更改。稍后,如果您将它从集合中移除,您可以再次改变它。我想说的是,将不可变数据结构(ala String 或您自己的类型,一直向下)与依赖于 hashCode 的集合(例如,HashMap 键或 HashSet)一起使用通常是最佳实践。

这取决于你如何称呼"lifetime"。您的确切 link 指出:

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

这意味着无法保证对象的哈希码在两个不同的运行应用程序[=]中保持一致.

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

合同确实保证了这一点,但仅此而已。

你们在谈论不同的事情。 如果你想使用 Hash(Map|Set) - 键应该是一个不可变的对象。 所以在这种情况下 hashCode 也是不可变的。 但在通常情况下,hashCode 应该随对象状态改变(根据对 hashCode 有意义的字段)。

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.

这并不常见,class 库中的某些 class 甚至指定了它们用于计算哈希码的确切公式 - 例如细绳。对于这些 classes,哈希码将始终相同。但是,虽然大多数 hashCode 实现都提供稳定的值,但您 不能 不依赖它。

此外,有些人认为 hashcode 是对象的唯一句柄。这是错误的,也是一种反模式。例如,字符串 "Aa" 和 "BB" 产生相同的 hashCode:2112。