Java映射集哈希代码不正确?

Java映射集哈希代码不正确?,java,hashmap,hashcode,Java,Hashmap,Hashcode,我从一组映射(Set)中得到了意外的结果,其中s.contains(s.iterator().next())为false 所讨论的集合只包含一个映射,即[{=262.666666667}(映射到字符串262.6666667)的空字符串 我无法提供一个简单的工作示例来复制该问题,如下所示: Set s = new HashSet<Map<String,String>>(); Map<String,String> m = new HashMap<>()

我从一组映射(
Set
)中得到了意外的结果,其中
s.contains(s.iterator().next())
false

所讨论的集合只包含一个映射,即
[{=262.666666667}
(映射到字符串
262.6666667
)的空字符串

我无法提供一个简单的工作示例来复制该问题,如下所示:

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()));
Set s=newhashset();
Map m=新的HashMap();
m、 认沽期权(“262.66667”);
s、 加(m);
System.out.println(s.contains(s.iterator().next());
HashMap不会覆盖hashCode,但抽象映射会覆盖它(见下文),因此我不认为在HashSet中放置HashMap有什么问题

public int hashCode()
{
     int h = 0;
     Iterator<Entry<K,V>> i = entrySet().iterator();
     while (i.hasNext())
         h += i.next().hashCode();
     return h;
}
public int hashCode()
{
int h=0;
迭代器i=entrySet().Iterator();
while(i.hasNext())
h+=i.next().hashCode();
返回h;
}
这种行为的原因是什么?我如何纠正它


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

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

    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()));
Set s=newhashset();
Map m=新的HashMap();
s、 加(m);
m、 认沽期权(“262.66667”);
System.out.println(s.contains(s.iterator().next());
也就是说,将映射添加到集合中,然后在映射中放置新的键/值


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

多线程?在我们得到重现问题的东西之前,很难帮助我们…当在单个线程上执行时,您的自包含示例返回
true
。您所说的意外结果是什么意思?可能是一些舍入问题?如果您在将成员映射添加到集合后修改它,从而更改映射的哈希代码,集合将被破坏。例如,这就是Python要求字典键不可变的原因。