Java 地图集hashCode不对?
Java Set of Maps hashCode incorrect?
我从一组地图 (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,我确实在添加后修改了地图,并通过在修改后添加而不是之前添加解决了问题。
如果您想重现错误,请按以下方式修改您的代码:
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()
以依赖于地图在那一刻持有的 key/value。 Set 在内部使用一个 Map,在您的 Map 被添加到集合中时,equals()
的值是键。当您向 Map 添加一个新的 key/value 时,equals()
返回的值也会发生变化并且与原始值不对应,这样您会得到 false for System.out.println(s.contains(s.iterator().next()));
我从一组地图 (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,我确实在添加后修改了地图,并通过在修改后添加而不是之前添加解决了问题。
如果您想重现错误,请按以下方式修改您的代码:
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()
以依赖于地图在那一刻持有的 key/value。 Set 在内部使用一个 Map,在您的 Map 被添加到集合中时,equals()
的值是键。当您向 Map 添加一个新的 key/value 时,equals()
返回的值也会发生变化并且与原始值不对应,这样您会得到 false for System.out.println(s.contains(s.iterator().next()));