似乎很多类(例如HashSet
)都认为对象的hashCode
不会改变。 documentation明确了equals
和hashCode
之间的关系应该是什么。
但实现一个在对象的生命周期内发生变化的hashCode
,设计是否很差?
答案 0 :(得分:6)
至少需要在hashCode冻结的应用程序中指出它在关注的集合中。通常,hashCode将在您构建对象时更改(例如,添加到ArrayList),然后将其添加到集合并停止更改。之后,如果您从集合中删除它,您可以再次改变它。我想说通常最好的做法是使用不可变的数据结构(ala String或你自己的类型一直有韵母)和依赖hashCode的集合(例如,HashMap键或HashSet)。
答案 1 :(得分:2)
不,当可变对象改变其内部状态时,hashCode会发生变化。
但是,一旦对象位于需要常量hashCode的位置,应用程序必须确保该对象不会发生变化,以便hashCode发生更改。
答案 2 :(得分:1)
这取决于你所谓的“生命周期”。您的确切链接指出:
每当在执行Java应用程序期间多次在同一对象上调用时,hashCode方法必须始终返回相同的整数
这意味着无法保证对象的哈希码在两个不同的应用程序运行之间保持一致。
但 保证在应用程序的给定运行中,即运行Java代码的JVM实例,对象的哈希代码永远不会改变。
合同确实保证了这一点,但仅此而已。
答案 3 :(得分:0)
你在谈论不同的事情。
如果你想使用Hash(Map|Set)
- 键应该是一个不可变的对象。
所以在这种情况下hashCode也是不可变的。
但是在常见情况下,应该使用对象状态更改hashCode(根据对hashCode有意义的字段)。
答案 4 :(得分:0)
hashCode
不能保证在不同的执行中得到相同的结果。正如javadocs所指出的那样 -
每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
这种情况并不常见,类库中的某些类甚至指定了用于计算哈希码的确切公式 - 例如串。对于这些类,哈希码将始终相同。但是,虽然大多数hashCode实现提供了稳定的值,但必须不依赖它。
此外,有些人认为hashcode
是对象的唯一句柄。这是错误的和反模式。例如,字符串“Aa”和“BB”产生相同的hashCode:2112。