Java:HashMap声称它有密钥,但不知何故没有

时间:2011-08-29 20:30:25

标签: java iterator set hashmap keyset

我有一个HashMap将Context类的对象映射到Integers。在Context类中,我确实覆盖了java.lang.Object的public int hashCode()和public boolean equals(Object c)。但是,我在迭代它时遇到了问题:

我希望(例如)获取分配给每个Context对象的Integer值,因此我遍历地图的键集。但它不起作用,因为地图显示它没有指定的密钥:

for (Context to : map.keySet()) {
    System.out.println("to-hash: " + to.hashCode());
    System.out.println("first-hash: " + map.keySet().iterator().next().hashCode());
    System.out.println("hashs equal: " + (to.hashCode()==map.keySet().iterator().next().hashCode()));
    System.out.println("to equals first: " + to.equals(map.keySet().iterator().next()));
    System.out.println("map has to? " + map.containsKey(to));
}

输出

to-hash: 156349
first-hash: 156349
hashs equal: true
to equals first: true
map has to? false

据我所知,当给定密钥时,映射首先检查哈希码是否匹配,然后检查是否相等。两者都是这里的情况,'to'对象的哈希码和键集中的第一个对象匹配,它们也是相等的。有趣的是,当我将hashCode()函数的返回值更改为常量(这是有效的,但出于性能原因不推荐)时,它可以正常工作。但我不明白为什么这会有所不同,因为156349 == 156349就像7 == 7。

我很困惑,我担心我会遗漏一些非常明显的东西,而且看不到它。如果是这样的话,对我感到羞耻,但是,我仍然会欣赏一个提示: - )

非常感谢!

1 个答案:

答案 0 :(得分:9)

如果您的Context对象以影响哈希代码的方式变为可变,并且您已经执行了一项操作,在将哈希代码放入地图。地图只会在插入点记录hashCode() 的值,然后在您尝试查找特定密钥时使用该值来查找匹配项。

如果将哈希函数设为常量,这将与它一致。基本上,在将哈希键放入地图后,不应该改变哈希键。

当然,这只是猜想,但它确实符合症状。