在Java中碰撞HashMap的有线事

时间:2016-12-21 03:50:00

标签: java hashmap bloom-filter

当我使用HashMap获取left_table和right_table之间的公共密钥时(我也在测试Bloom Filter算法与HashMap进行比较,所以我添加了标记{{1要引起注意,Bloom Filter可能有这个问题),我声明了两个HashMap,当我把right_table中的键放到HashMap hm1 and hm2(默认值为1)时,键总是发生碰撞。我意识到密钥的哈希值可能是相同的,但为什么它总是出现在同一个地方。当我重新安排hm2hm1的声明时,碰撞仍然存在!

我测试hm2总是等于n是正确的,它可以存储超过hm1.size2000000 uuids中的HashMap工具是否可靠?

Java

上一代码的输出是:

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Random;
    import java.util.UUID;

    public class HashMapBugTest {
        public static void main(String[] argv) {
            int n = 100;
            int real = 10;
            List<String> Uuids_in_left_table = new ArrayList<String>();

            // init left table
            Long startInsertTime1 = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            String Uuid = UUID.randomUUID().toString();
            Uuids_in_left_table.add(Uuid);
        }
        Long endInsertTime1 = System.currentTimeMillis();
        System.out.println("The length of Uuids_in_left_table is:" + Uuids_in_left_table.size());
        System.out.println("The time use for insert the uuid into the left table used " + (endInsertTime1 - startInsertTime1) + "ms.");

        // init right table
        List<String> Uuids_in_right_table = new ArrayList<String>();
        Random r = new Random(n);
        Long startInsertTime2 = System.currentTimeMillis();
        for (int i = 0; i < n - real; i++) {
            String Uuid = UUID.randomUUID().toString();
            Uuids_in_right_table.add(Uuid);
        }
        for (int i = 0; i < real; i++) {
            String Uuid = Uuids_in_left_table.get(r.nextInt(n));
            Uuids_in_right_table.add(Uuid);
        }
        Long endInsertTime2 = System.currentTimeMillis();
        System.out.println("The length of Uuids_in_left_table is: " + Uuids_in_left_table.size());
        System.out.println("The time use for insert the uuid into the right table used " + (endInsertTime2 - startInsertTime2) + "ms.");

        // build hashmap
        HashMap<String, Object> hm2 = new HashMap<String, Object>();
        HashMap<String, Object> hm1 = new HashMap<String, Object>();
        for (int i = 0; i < n; i++) {
            int ind = hm2.size();
            if (ind == 97)
                System.out.println(hm2.containsKey(Uuids_in_right_table.get(ind)));
            hm2.put(Uuids_in_right_table.get(i), 1);
            if (ind == hm2.size())
                System.out.println("a"+i+"---"+Uuids_in_right_table.get(i));
        }
        for (int i = 0; i < n; i++) {
            hm1.put(Uuids_in_left_table.get(i), 1);
        }

        int cnt = 0;
        System.out.println("length of hm1 is:" + hm1.size());
        System.out.println("length of hm2 is:" + hm2.size());
        Long startHashMapTime = System.currentTimeMillis();
        for (String str:hm1.keySet()) {
            if (hm2.containsKey(str))
                cnt += 1;
        }
        Long endHashMapTime = System.currentTimeMillis();
        System.out.println("The time used for check the uuid common in the left table and right table used " + (endHashMapTime - startHashMapTime) + "ms.");
        System.out.println("The number of common uuid is:" + cnt);
    }
}

1 个答案:

答案 0 :(得分:0)

你的问题如此可重复的原因是这一行:

Random r = new Random(n);

它没有按照你的想法做到。

它的作用:它创建一个带有初始种子n的随机生成器。 由于n在你的程序中总是10,这意味着你总是得到相同的随机数序列。

始终将从左侧列表中挑选的10个uuid完全导入右侧列表,并且索引88使用两次。

修正:

Random r = new Random();

这将创建一个随机生成器,其初始种子基于当前时间(以毫秒为单位),因此每次运行该程序时,您很可能会得到10个不同的10个数字列表。

您的代码未突出显示HashMap中的任何问题。如果将同一个键(左侧列表中索引88的uuid)插入hm2两次,则第二次插入时将覆盖第一次插入时。而不是你想象的100个元素,它只包含99个元素。