Java Map :: hashCode()碰撞 - 为什么?

His*_*ham 4 java map hashcode collision

以下代码导致为两个地图生成相同的哈希码,任何想法?


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());


    }
}

Run Code Online (Sandbox Code Playgroud)

结果是:

-1376467648
-1376467648
Run Code Online (Sandbox Code Playgroud)

简单地更改密钥名称就足以使代码生成两个不同的哈希代码.

Jon*_*eet 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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

campaignId=4770: -1318251287
campaignId=4936: -1318251261
lazy=true: 3315643
lazy=false: 3315617
Run Code Online (Sandbox Code Playgroud)

因此,在一对中,第一个地图的散列比第二个地图 26 ,而在另一个地图中,第一个地图的散列比第二个地图 26 个.

AbstractMap 只是总结哈希值(一种确保排序无关紧要的方法),所以两者最终得到相同的哈希码.

它真的Boolean.hashCode()很像这样:

return value ? 1231 : 1237;
Run Code Online (Sandbox Code Playgroud)

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

return (int)(value ^ (value >>> 32));
Run Code Online (Sandbox Code Playgroud)

鉴于他们碰巧选择的值Boolean.hashCode(),如果你的long价值只相差26(或相隔26*2 ^ 32)那么你会遇到同样的事情.


Viv*_*sse 6

我认为这只是一个巧合.从用于AbstractMap的Javadoc #hashCode():

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

对于Entry#hashCode():

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

 (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
 (e.getValue()==null ? 0 : e.getValue().hashCode())
Run Code Online (Sandbox Code Playgroud)

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