有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java hashCode()是否可以动态更改内容?

在我的实现中,我有一个重写equals(Object)和hashCode()的类a。但是我有一个小小的疑问,当把a的实例添加到HashSet/HashMap时,hashCode()的值是x,过了一段时间,同一个hashCode()的值变为y。这会有什么影响吗


共 (4) 个答案

  1. # 1 楼答案

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

    编辑:如前所述,它取决于容器。显然,如果容器从不使用hashCodeequals方法,就不会出错。但一旦它试图比较事物是否相等(所有地图和集合),你就会陷入麻烦

  2. # 2 楼答案

    对。很多人在这里回答了这个问题,我只是想打个比方。哈希代码类似于基于哈希的集合中的地址:

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

  3. # 3 楼答案

    将哈希代码添加到映射/集后,哈希代码不得更改。在此之前进行更改是可以的,不过如果更改,通常会使类型更易于使用

    如果哈希代码发生更改,则在映射/集合中找不到密钥,因为即使它最终位于同一个bucket中,哈希代码也将首先更改

  4. # 4 楼答案

    当对象包含在HashMap/HashSet等中时,hashCode()equals()的返回值更改时,行为未定义(可能会出现各种奇怪的行为)。因此,当对象包含在这样的集合中时,必须避免密钥的这种变异

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

    举个例子,在映射中使用一个列表作为键通常被认为是可以的,但是您应该避免在应用程序的任何一点上修改这样的列表,以避免被讨厌的bug咬到

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