Java Map::hashCode() 冲突 - 为什么?
以下代码会为两个映射生成相同的哈希码,有什么想法吗?
import java.util.HashMap;
import java.util.Map;
public class Foo
{
@SuppressWarnings("unchecked")
public static void main (String[] args)
{
Map map;
map = new HashMap();
map.put("campaignId", 4770L);
map.put("location", "MINI_PROFILE");
map.put("active", "true");
map.put("lazy", true);
System.out.println(map.hashCode());
map = new HashMap();
map.put("campaignId", 4936L);
map.put("location", "MINI_PROFILE");
map.put("active", "true");
map.put("lazy", false);
System.out.println(map.hashCode());
}
}
结果是:
-1376467648
-1376467648
只需更改键名就足以使代码生成两个不同的哈希码。
The following code results in the same hash code being generated for the two maps, any ideas?
import java.util.HashMap;
import java.util.Map;
public class Foo
{
@SuppressWarnings("unchecked")
public static void main (String[] args)
{
Map map;
map = new HashMap();
map.put("campaignId", 4770L);
map.put("location", "MINI_PROFILE");
map.put("active", "true");
map.put("lazy", true);
System.out.println(map.hashCode());
map = new HashMap();
map.put("campaignId", 4936L);
map.put("location", "MINI_PROFILE");
map.put("active", "true");
map.put("lazy", false);
System.out.println(map.hashCode());
}
}
The result is:
-1376467648
-1376467648
Simply changing the key names is enough to make the code generate two different hash codes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这并非巧合。
两者中的字符串对象是相同的。相同的对象将给出相同的哈希码。
It is not a coincident.
String objects are same in both. Same object will give same hashcode.
发生碰撞。事实上,您可以重写 hashCode() 以始终为每个
HashMap
返回 0,这将是正确的(尽管它会使许多结构变慢)。Collisions happen. In fact, you could override hashCode() to always return 0 for every
HashMap
and it would be correct (altough it would make a lot of structures slow).我认为这只是一个巧合。来自 AbstractMap#hashCode() 的 Javadoc:
对于 Entry#hashCode():
因此映射的哈希码基于映射中包含的键和值。您只是遇到了一种奇怪的情况,两个映射具有相同的哈希码,没有明显的原因。
I think this is just a coincidence. From the Javadoc for AbstractMap#hashCode():
And for Entry#hashCode():
So hash codes for maps are based on both the keys AND the values contained in the map. You're just experiencing a odd situation where two maps have the same hash code, with no apparent reason.
我怀疑这只是巧合……肯定会发生冲突,在这种情况下,第一个值中的相关不同位看起来实际上正在丢失。
然而,它不应该有任何区别 - 任何使用哈希码的东西必须应对冲突。
编辑:这只是哈希值的计算方式。此代码显示了发生的情况:
结果:
因此,在一对中,第一个映射的哈希值比第二个映射少 26,而在另一对中,第一个映射的哈希值多 em> 比第二张地图。
AbstractMap
只是对哈希值求和(确保排序无关的一种方法),因此两者最终得到相同的哈希码。这实际上取决于
Boolean.hashCode()
,如下所示:... 和
Long.hashCode()
,如下所示:鉴于他们碰巧选择的值
Boolean.hashCode()
,如果您的long
值仅相距 26(或 26 * 2^32 相距),那么您将遇到同样的情况。Simply coincidence, I suspect... there are bound to be collisions, and in this case it looks like the relevant different bits in the first value are being lost, effectively.
However, it shouldn't make any difference - anything using hash codes must cope with collisions.
EDIT: It's just the way the hashes happen to be calculated. This code shows what's going on:
Results:
So in one pair the first map has a hash 26 less than the second map, and in another pair the first map has a hash 26 more than the second map.
AbstractMap
just sums hash values (one way of making sure that ordering is irrelevant) so the two end up with the same hash code.It's really down to
Boolean.hashCode()
which looks like this:... and
Long.hashCode()
which looks like this:Given the values they happened to pick in
Boolean.hashCode()
, if yourlong
values are only 26 apart (or 26 * 2^32 apart) then you'll run into the same thing.