Java Set of maps hashCode不正确?

时间:2015-03-26 10:40:51

标签: java hashmap hashcode

我从一组地图(Set<Map<String,String>>)获得意外结果,其中s.contains(s.iterator().next())false

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

我无法将一个复制问题的最小工作示例放在一起,因为以下输出为true:

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但是抽象地图会覆盖(见下文)所以我没有看到将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,我确实在添加后修改了地图,并通过在修改后添加而不是之前添加来解决问题。

1 个答案:

答案 0 :(得分:3)

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

    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()));

即,将地图添加到集合中,然后在地图中添加新的键/值。

问题在于,正如您所说,抽象地图会覆盖equals()以依赖于该时刻地图所保存的键/值。 Set在内部使用Map,作为将Map添加到集合时equals()的值的关键。当您向地图添加新的键/值时,equals()返回的值也会更改,并且与原始值不对应,这样您就会System.out.println(s.contains(s.iterator().next()));