【问题标题】:Java Set of Maps hashCode incorrect?Java Set of Maps hashCode 不正确?
【发布时间】:2015-03-26 10:40:51
【问题描述】:

我从一组地图 (Set<Map<String,String>>) 中得到了意想不到的结果,其中 s.contains(s.iterator().next())false

有问题的集合只包含一个映射[{=262.666666666666667}](空字符串映射到字符串262.666666666666667)。

我无法组合一个最小的工作示例来复制问题,因为以下输出为真:

Set s = new HashSet<Map<String,String>>();
Map<String,String> m = new HashMap<>();
m.put("", "262.666666666666667");
s.add(m);
System.out.println(s.contains(s.iterator().next()));

HashMap 不会覆盖 hashCode 但 Abstract map 会(见下文),所以我看不到将 HashMap 放入 HashSet 的问题。

public int hashCode()
{
     int h = 0;
     Iterator<Entry<K,V>> i = entrySet().iterator();
     while (i.hasNext())
         h += i.next().hashCode();
     return h;
}

这种行为的原因是什么,我该如何解决?

编辑:感谢 doublep 和 morgano,我确实在添加地图后修改了地图,并通过在修改后而不是之前添加解决了问题。

【问题讨论】:

  • 多线程?在我们得到重现问题的某事之前,很难提供帮助...
  • 您的独立示例在单线程上执行时返回true
  • 意外结果是什么意思?
  • 可能是一些舍入问题?
  • 如果你修改了成员地图之后添加到集合中,从而改变了地图的哈希码,集合将被破坏。这就是 Python 要求字典键不可变的原因。

标签: java hashmap hashcode


【解决方案1】:

如果您想重现错误,请以这种方式修改您的代码:

    Set s = new HashSet<Map<String,String>>();
    Map<String,String> m = new HashMap<>();
    s.add(m);
    m.put("", "262.666666666666667");
    System.out.println(s.contains(s.iterator().next()));

即把map添加到set中,然后在map中放一个新的key/value。

问题在于,正如您所说,抽象映射会覆盖 equals() 以依赖于映射当时持有的键/值。 Set 在内部使用一个 Map,在您的 Map 被添加到集合时,它是 equals() 的值的键。当您向 Map 添加新的键/值时,equals() 返回的值也会发生变化,并且与原始值不对应,这样您就会得到 System.out.println(s.contains(s.iterator().next())); 的 false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    相关资源
    最近更新 更多