hashCode()可以动态更改内容吗?

时间:2011-05-16 05:49:35

标签: java

在我的实现中,我有一个类A,它覆盖equals(Object)和hashCode()。但我有一个小小的疑问,即在向HashSet / HashMap添加A的实例时,hashCode()的值是x,之后相同的hashCode()的值更改为y。它会影响什么吗?

4 个答案:

答案 0 :(得分:7)

哈希码在添加到地图/集后不得更改。它可以在此之前进行更改,但如果没有更改它通常会使类型更容易使用。

如果哈希码发生变化,则不会在map / set中找到密钥,因为即使它最终在同一个桶中,哈希码也会先被更改。

答案 1 :(得分:3)

如果对象包含在hashCode() / equals()等中,HashMapHashSet的返回值发生变化,则行为未定义(您可以获得各种奇怪的行为)。因此,当对象包含在此类集合等中时,必须避免密钥的这种变异。

最好只使用不可变对象作为键(或将它们放在HashSet等中)。实际上,例如python不允许将可变对象用作映射中的键。在Java中使用可变对象作为键是允许/通用的,但在这种情况下,建议使这些对象“有效地不可变”。即实例化后,根本不要更改此类对象的状态。

举一个例子,使用列表作为Map中的键通常被认为是可以的,但是你应该避免在你的应用程序的任何一点改变这样的列表,以避免被令人讨厌的错误所困扰。

只要在对象位于容器中时不更改hashCode()equals()的返回值,您就可以在纸上完成了。但是人们可能很容易引入令人讨厌的,难以发现的错误,所以最好完全避免这种情况。

答案 2 :(得分:2)

是的,对象的哈希码在其生命周期内不得更改。如果是,则需要通知容器(如果可能的话);否则你会得到错误的结果。

编辑:正如所指出的,它取决于容器。显然,如果容器从不使用您的hashCodeequals方法,则不会出现任何问题。但是一旦它试图比较事物的平等(所有地图和集合),你就会遇到麻烦。

答案 3 :(得分:1)

是。很多人在这里回答了这个问题,我只是想说一个类比。散列代码类似于基于散列的集合中的地址:

想象一下,您以“Mike”的名义入住酒店,然后在支票据上将您的名字改为“GreatMike”。然后当有人用你的名字“迈克”找你时,他再也找不到你了。