我从一组地图(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,我确实在添加后修改了地图,并通过在修改后添加而不是之前添加来解决问题。
答案 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()));