java hashCode()是否可以动态更改内容?
在我的实现中,我有一个重写equals(Object)和hashCode()的类a。但是我有一个小小的疑问,当把a的实例添加到HashSet/HashMap时,hashCode()的值是x,过了一段时间,同一个hashCode()的值变为y。这会有什么影响吗
你可以在下面搜索框中键入要查询的问题!
在我的实现中,我有一个重写equals(Object)和hashCode()的类a。但是我有一个小小的疑问,当把a的实例添加到HashSet/HashMap时,hashCode()的值是x,过了一段时间,同一个hashCode()的值变为y。这会有什么影响吗
# 1 楼答案
是的,对象的哈希代码在其生存期内不得更改。如果有,您需要通知容器(如果可能);否则你将得到错误的结果
编辑:如前所述,它取决于容器。显然,如果容器从不使用
hashCode
或equals
方法,就不会出错。但一旦它试图比较事物是否相等(所有地图和集合),你就会陷入麻烦# 2 楼答案
对。很多人在这里回答了这个问题,我只是想打个比方。哈希代码类似于基于哈希的集合中的地址:
想象一下,你以“迈克”的名字入住一家酒店,然后在支票上把你的名字改为“GreatMike”。然后当有人用你的名字“迈克”找你时,他再也找不到你了
# 3 楼答案
将哈希代码添加到映射/集后,哈希代码不得更改。在此之前进行更改是可以的,不过如果不更改,通常会使类型更易于使用
如果哈希代码发生更改,则在映射/集合中找不到密钥,因为即使它最终位于同一个bucket中,哈希代码也将首先更改
# 4 楼答案
当对象包含在
HashMap
/HashSet
等中时,hashCode()
或equals()
的返回值更改时,行为未定义(可能会出现各种奇怪的行为)。因此,当对象包含在这样的集合中时,必须避免密钥的这种变异最好只对键使用不可变对象(或将它们放在
HashSet
等中)。事实上,例如python,不允许将可变对象用作映射中的键。在Java中使用可变对象作为键是允许的/常见的,但在这种情况下,建议将此类对象设置为“有效不可变”。也就是说,实例化之后,根本不改变这些对象的状态举个例子,在映射中使用一个列表作为键通常被认为是可以的,但是您应该避免在应用程序的任何一点上修改这样的列表,以避免被讨厌的bug咬到
只要在对象位于容器中时不更改
hashCode()
和equals()
的返回值,您就可以在纸面上确定。但是很容易错误地引入讨厌的、难以发现的bug,所以最好完全避免这种情况