【问题标题】:A wired thing in collide of HashMap in JavaJava中HashMap碰撞中的有线事物
【发布时间】:2016-12-21 03:49:59
【问题描述】:

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

我已经测试hm1.size 总是等于 n 这是正确的,它可以存储超过2000000 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);
    }
}

前面代码的输出是:

The length of Uuids_in_left_table is:100
The time use for insert the uuid into the left table used 20ms.
The length of Uuids_in_left_table is: 100
The time use for insert the uuid into the right table used 3ms.
true
a97---c3b4f281-d82e-42c5-9a6d-b4de19032689
true
length of hm1 is:100
length of hm2 is:99
The time used for check the uuid common in the left table and right table used 0ms.
The number of common uuid is:9

【问题讨论】:

  • 我添加标签布隆过滤器来获得关注。这就是你获得负面关注的方式。
  • 您的问题到底是什么?你期待什么行为?你找到了什么?你想证明什么?

标签: java hashmap bloom-filter


【解决方案1】:

您的问题如此可重现的原因是这一行:

Random r = new Random(n);

它没有做你认为它做的事情。

它的作用:它使用初始种子n 创建一个随机生成器。 由于n 在您的程序中始终为 10,这意味着您始终会得到相同的随机数序列。

总是从左侧列表中选择完全相同的 10 个 uuid 到右侧列表中,并且索引 88 被使用了两次。

修复:

Random r = new Random();

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

您的代码没有突出显示HashMap 中的任何问题。如果您在hm2 中两次插入相同的键(左侧列表中索引 88 中的 uuid),那么第二次插入时会覆盖第一次插入时。而不是您预期的 100 个元素,它只包含 99 个元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-28
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多