似乎许多类(例如
但是,实现一个在对象生命周期内会更改的
HashSet
)都假定对象的hashCode
不会改变。 在文档中很清楚地说明了equals
和hashCode
之间的关系。但是,实现一个在对象生命周期内会更改的
hashCode
是否是不良设计?在应用程序中,至少需要有一个点,在这个点上,hashCode在关心它的集合中被冻结。通常情况下,在构建对象时(例如,添加到ArrayList中),hashCode会发生变化,然后您将其添加到集合中并停止更改。稍后,如果您从集合中删除它,则可能会再次突变。我认为,使用不可变数据结构(如String或自己定义的类型,其中包含所有final)与依赖于hashCode的集合(例如HashMap键或HashSet)通常是最佳实践。
当可变对象改变其内部状态时,hashCode发生变化是可以的。
但是,一旦该对象处于期望常量hashCode的位置,应用程序必须确保该对象不会被修改以使hashCode发生变化。
hashCode()
/equals()
关系,一个对象的 hashCode()
方法是否可以返回不同的值?”。我的评论只是关于你回答中提到的一部分,即在单个执行期间哈希码保证不会改变。我认为你的意思是即使你相应地更改了 equals()
,也不能更改它。 - CinnamHash(Map|Set)
- 键应该是不可变对象。
因此,在这种情况下,hashCode 也将是不可变的。
但在一般情况下,hashCode 应该随着对象状态改变(根据对于 hashCode 有意义的字段)。hashCode
不能保证在不同的执行中返回相同的结果。正如Javadoc所指出的:
在Java应用程序的执行过程中,如果对同一对象调用多次hashCode方法,则只要equals比较中使用的信息没有被修改,hashCode方法就必须始终返回相同的整数。这个整数不需要在同一应用程序的不同执行之间保持一致。
虽然大多数hashCode实现提供稳定的值,但这种情况并不常见,甚至类库中的某些类还会指定它们用于计算哈希码的确切公式,例如String类。对于这些类,哈希码将始终相同。但是,您不能依赖于它。
此外,有些人认为hashcode
是对象的唯一句柄。这是错误的和反模式的。例如,字符串"Aa"和"BB"产生相同的hashCode:2112。