new HashMap(list.size())指定size就能完全避免扩容带来的额外开销了吗?

public static void longLongAGo() {
    int count = 1000000;

    System.out.println("---------------- 不设置hashMap初始容量 ------------");
    long start = System.currentTimeMillis();
    HashMap<Integer, Object> map = new HashMap<>();
    for (int i = 0; i < count; i++) {
        map.put(i, UUID.randomUUID());
    }
    long end = System.currentTimeMillis();
    System.out.println("添加1000000个元素耗时:" + (end - start));

    System.out.println("---------------- 设置hashMap初始容量 -------------------");
    long start1 = System.currentTimeMillis();
    HashMap<Integer, Object> map1 = new HashMap<>(count);
    for (int i = 0; i < count; i++) {
        map1.put(i, UUID.randomUUID());
    }
    long end1 = System.currentTimeMillis();
    System.out.println("添加1000000个元素耗时:" + (end1 - start1));
}

在初始化的时候设定了map的容量,不会在添加元素的过程中进行自动扩容了,大大提高了性能,从结果看确实如此!所以,集合初始化时,指定集合初始值大小能提升性能。

当设置初始容量为1000000时,容器并不是想象中的不扩容了,而是也扩容了1次:

 public static void longLongAGo() throws Exception {
        int count = 1000000;

        System.out.println("---------------- 初始化hashMap容量为1000000 ------------");
        int resizeCount = 0;
        HashMap<Integer, Object> map = new HashMap<>(count);
        Method capacityMethod = map.getClass().getDeclaredMethod("capacity");
        capacityMethod.setAccessible(true);
        int capacity = (int) capacityMethod.invoke(map);
        System.out.println("初始容量:" + capacity);
        for (int i = 0; i < count; i++) {
            map.put(i, UUID.randomUUID());
            int curCapacity = (int) capacityMethod.invoke(map);
            if (curCapacity > capacity) {
                System.out.println("当前容量:" + curCapacity);
                resizeCount++;
                capacity = curCapacity;
            }
        }
        System.out.println("hashMap扩容次数:" + resizeCount);
    }

 

/**
 * Returns a power of two size for the given target capacity.
 */
static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

细想下扩容原理即可知道

完美的方式之一可以用:

Maps.newHashMapWithExpectedSize(list.size())

 

源码:

/**
 * Returns a capacity that is sufficient to keep the map from being resized as
 * long as it grows no larger than expectedSize and the load factor is >= its
 * default (0.75).
 */
static int capacity(int expectedSize) {
  if (expectedSize < 3) {
    checkNonnegative(expectedSize, "expectedSize");
    return expectedSize + 1;
  }
  if (expectedSize < Ints.MAX_POWER_OF_TWO) {
    return expectedSize + expectedSize / 3;
  }
  return Integer.MAX_VALUE; // any large value
}

Maps.newHashMapWithExpectedSize(list.size())

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值