gpt4 book ai didi

java - HashMap 中键的突变会导致错误的结果

转载 作者:行者123 更新时间:2023-12-01 07:48:01 25 4
gpt4 key购买 nike

在我的项目中,我使用HashMap来存储一些数据,最近我发现当我改变HashMap的键时,可能会发生一些意想不到的错误结果。例如:

HashMap<ArrayList,Integer> a = new HashMap<>();
ArrayList list1 = new ArrayList<>();
a.put(list1, 1);
System.out.println(a.containsKey(new ArrayList<>())); // true
list1.add(5);
ArrayList list2 = new ArrayList<>();
list2.add(5);
System.out.println(a.containsKey(list2)); // false

请注意,a.keySet().iterator().next().hashCode() == list2.hashCode()a.keySet().iterator() .next().equals(list2) 为 true。

我无法理解为什么会发生这种情况,因为这两个对象相等并且具有相同的哈希码。有谁知道这是什么原因,以及是否有任何其他类似的结构允许 key 突变?谢谢。

最佳答案

可变键始终是一个问题。如果突变可以改变键的哈希码和/或equals()的结果,则键被认为是可变的。话虽这么说,列表通常会生成哈希码并根据其元素检查相等性,因此它们几乎永远不会成为映射键的良好候选者。

你的例子有什么问题?添加键时,它是一个空列表,因此会生成与包含元素时不同的哈希码。因此,即使在更改键列表后,键和 list2 的哈希码相同,您也找不到该元素。为什么?仅仅是因为 map 看起来在错误的存储桶中。

示例(简化):

让我们从一些假设开始:

  • 空列表返回哈希码 0
  • 如果列表包含元素 5,则返回哈希码 5
  • 我们的 map 有 16 个桶(默认)
  • 存储桶索引由哈希码 % 16(我们的存储桶数量)决定

如果您现在添加空列表,由于其哈希码,它会被插入到存储桶 0 中。

当您使用 list1 进行查找时,由于哈希码为 5,它将在存储桶 5 中查找。由于该存储桶为空,因此什么也找不到。

问题是您的 key 列表更改了其哈希码,因此应该放入不同的存储桶中,但 map 不知道应该发生这种情况(这样做可能会导致一堆其他问题)。

关于java - HashMap 中键的突变会导致错误的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45977296/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com