【问题标题】:Better way to detect HashMap contains the same List or not [duplicate]检测HashMap的更好方法是否包含相同的列表[重复]
【发布时间】:2019-08-05 14:35:10
【问题描述】:

我有一个List,它将被超时更改,我想将它与时间值一起存储,并检查相同的List 是否再次出现。

例如:

[1, 2, 3] is same as [1, 2, 3]

我认为既然List<Integer>是通过引用值传递的,所以我认为key应该被字符串化才能使用。

例如:

Map<String, Integer> = new HashMap<>()
(key:"stringified key", value: .....)

但我发现Map&lt;List&lt;Integer&gt;, Integer&gt; map = new HashMap&lt;&gt;() 也可以工作,但我不知道为什么可以工作,因为无论列表中的值发生什么变化,键都应该引用同一个列表。

例如:

(key:[reference to key], value: .....)
List<Integer> testList = new ArrayList<>();
testList.add(0);
map.put(testList, 0);
testList.set(0, 1);
if(map.containsKey(testList))System.out.println("duplicate");
else System.out.println("unique");

上面的结果将打印“唯一”,但我认为它应该打印“重复”。 为什么上面的结果会这样?

【问题讨论】:

  • 永远不要修改地图中的关键对象。不可预测的行为是肯定的。而是删除映射,修改密钥并重新插入。在这种情况下,您获得 unique 的原因是列表的哈希码已更改,因此哈希映射即使在其中也无法找到它,只是现在存储在错误的哈希值下。或者,您可能可能将您的列表包装在一个对象中,该对象的哈希码不依赖于列表,但这会很丑陋且难以维护。所以我建议你不要。
  • ...代码块的最后一行else System.out.println("unique); 缺少引号

标签: java list hashmap


【解决方案1】:

由于 yoy 更改了 ArrayList 的内容,ArrayList hashCode 的值也发生了变化。

List<Integer> l = new ArrayList<>();
l.add(0); 
System.out.println(l.hashCode()); // 31
l.set(0, 1);
System.out.println(l.hashCode()); // 32

这违背了HashMap 的原则,其中hashCode 用于查找元素的位置。用于HashMap 键的对象应具有常量hashCode,否则HashMap 查找逻辑将不起作用。

【讨论】:

  • 是这种bug吗?因为哈希码已更新为ArrayList,但未在哈希桶中
  • @Deadpool HashMap 使用 hashCode 值在插入时选择存储桶。如果在查找过程中使用了不同的hashCode,它将查看不同的存储桶并且找不到该值。
猜你喜欢
  • 2020-03-30
  • 1970-01-01
  • 1970-01-01
  • 2013-09-23
  • 1970-01-01
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多