4

以下代码导致为两个地图生成相同的哈希码,有什么想法吗?


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

只需更改键名就足以使代码生成两个不同的哈希码。

4

4 回答 4

9

只是巧合,我怀疑......肯定会发生冲突,在这种情况下,看起来第一个值中的相关不同位正在有效地丢失。

然而,它不应该有任何区别——任何使用哈希码的东西都必须应对冲突。

编辑:这只是哈希值的计算方式。这段代码显示了发生了什么:

import java.util.*;

public class Test
{
    @SuppressWarnings("unchecked")
    public static void main (String[] args)
    {
        AbstractMap.SimpleEntry[] entries = {
            new AbstractMap.SimpleEntry("campaignId", 4770L),
            new AbstractMap.SimpleEntry("campaignId", 4936L),
            new AbstractMap.SimpleEntry("lazy", true),
            new AbstractMap.SimpleEntry("lazy", false)
        };
        for (AbstractMap.SimpleEntry entry : entries) {
            System.out.println(entry + ": " + entry.hashCode());
        }
    }
}

结果:

campaignId=4770: -1318251287
campaignId=4936: -1318251261
lazy=true: 3315643
lazy=false: 3315617

因此,在一对中,第一个映射的哈希值比第二个映射小 26 而在另一对中,第一个映射的哈希值第二个映射大 26。

AbstractMap只是对哈希值求和(确保排序无关紧要的一种方法),因此两者最终得到相同的哈希码。

这真的Boolean.hashCode()是这样的:

return value ? 1231 : 1237;

...Long.hashCode()看起来像这样:

return (int)(value ^ (value >>> 32));

鉴于他们碰巧选择的值Boolean.hashCode(),如果您的long值仅相差 26(或 26 * 2^32),那么您将遇到同样的事情。

于 2010-09-02T20:23:14.437 回答
6

我认为这只是一个巧合。来自 AbstractMap#hashCode() 的 Javadoc:

映射的哈希码定义为映射的 entrySet() 视图中每个条目的哈希码的总和。

对于 Entry#hashCode():

返回此映射条目的哈希码值。映射条目 e 的哈希码定义为:

 (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
 (e.getValue()==null ? 0 : e.getValue().hashCode())

因此,地图的哈希码基于地图中包含的键和值。您只是遇到了一种奇怪的情况,即两个地图具有相同的哈希码,没有明显的原因。

于 2010-09-02T20:24:48.180 回答
3

发生碰撞。实际上,您可以覆盖 hashCode() 以始终为每个返回 0HashMap并且它是正确的(尽管它会使很多结构变慢)。

于 2010-09-02T20:28:19.850 回答
0

这不是巧合。

字符串对象在两者中都是相同的。相同的对象将给出相同的哈希码。

于 2013-06-21T12:07:39.653 回答