java HashMap初始化容量的效率问题

新手上路,请多包涵

问题描述

在本机测试用例中,初始化键值对100W,初始化容量200W(其实当键值对更少,比如10W,5W等级别,情况也是类似的),发现初始化容量的效率和不初始化容量的效率并不是稳定不变的,为何一直听说当可预估map内容大小时,应该预填容量值呢?

测试代码

int puts = 1000000, cap = puts * 2;
for (int k = 0; k < 5; k++) {
    System.out.println("=========独立测试开始==========");
    HashMap<Integer, Integer> map5 = new HashMap<Integer, Integer>(cap);
    long time01Start = System.currentTimeMillis();
    for (int i = 0; i < puts; i++) {
        map5.put(i, i);
    }

    System.out.println("HashMap初始化容量" + puts / 10000 + "W的耗时:" + (System.currentTimeMillis() - time01Start) + "ms");

    HashMap<Integer, Integer> map6 = new HashMap<Integer, Integer>();
    long time02Start = System.currentTimeMillis();
    for (int i = 0; i < puts; i++) {
        map6.put(i, i);
    }

    System.out.println("HashMap未初始化容量" + puts / 10000 + "W的耗时:" + (System.currentTimeMillis() - time02Start) + "ms");
    System.out.println("=========独立测试结束==========");
}

5次的测试结果

=========独立测试开始==========
HashMap初始化容量100W的耗时:964ms
HashMap未初始化容量100W的耗时:603ms
=========独立测试结束==========
=========独立测试开始==========
HashMap初始化容量100W的耗时:119ms
HashMap未初始化容量100W的耗时:658ms
=========独立测试结束==========
=========独立测试开始==========
HashMap初始化容量100W的耗时:26ms
HashMap未初始化容量100W的耗时:72ms
=========独立测试结束==========
=========独立测试开始==========
HashMap初始化容量100W的耗时:154ms
HashMap未初始化容量100W的耗时:34ms
=========独立测试结束==========
=========独立测试开始==========
HashMap初始化容量100W的耗时:134ms
HashMap未初始化容量100W的耗时:34ms
=========独立测试结束==========
阅读 7.3k
3 个回答

测试方法不太科学。

  1. 最好分开独立测试,放在循环里也不是不行,只是有时候结果不太准确,每次循环之间可能会有影响

  2. 考虑JVM内存大小对结果可能产生的影响

  3. 应该测试两种情况:预分配容量和不预分配容量的先后顺序可能会对结果有影响,哪个先哪个后应该各占测试次数的一半(个人感觉题主的结果应该主要是受到了这一条的影响

  4. 测试数据应该再随机一点,而不是用一个循环然后不断i++。最好能够使用随机字符串或其他对象进行测试(为避免创建对象的影响,可以预先生成所有数据)

  5. 考虑loadFactor的设置

你运行时的JVM堆多大?

初始化不是应该用

     public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        init();
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题