美文网首页JAVA集合
HashMap初始容量和扩容

HashMap初始容量和扩容

作者: 不将就51y | 来源:发表于2018-02-14 15:59 被阅读0次

《阿里巴巴Java开发手册》中对于HashMap有推荐用法



那么HashMap是如何扩容的呢?通过查阅源码可以看出

static final float DEFAULT_LOAD_FACTOR = 0.75f;

public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

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;
        this.threshold = tableSizeFor(initialCapacity);
    }

/**
     * 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;
    }

通过HashMap#tableSizeFor可以看出HashMap的初始容量并非initialCapacity,而是min(2^n)>initialCapacity,即大于initialCapacity的2的n次幂的最小值。而扩容条件只要HashMap的容量大于threshold*loadFactor时就需要扩容,而非初始值initialCapacity,这样可能与我们的预期不符,本意可能是在initialCapacity范围内都不需要扩容,举例如下:


解决方案

其中Guava的Maps提供了解决方案

public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
    return new HashMap<>(capacity(expectedSize));
  }

static int capacity(int expectedSize) {
    if (expectedSize < 3) {
      checkNonnegative(expectedSize, "expectedSize");
      return expectedSize + 1;
    }
    if (expectedSize < Ints.MAX_POWER_OF_TWO) {
      // This is the calculation used in JDK8 to resize when a putAll
      // happens; it seems to be the most conservative calculation we
      // can make.  0.75 is the default load factor.
      return (int) ((float) expectedSize / 0.75F + 1.0F);
    }
    return Integer.MAX_VALUE; // any large value
  }

这样HashMap的容量在小于或等于expectedSize时都不需要扩容。


相关文章

  • HashMap

    Q: HashMap什么时候会进行扩容?HashMap在初始化时可以给定初始容量和负载因子,默认的初始容量和负载因...

  • HashMap初始容量和扩容

    《阿里巴巴Java开发手册》中对于HashMap有推荐用法 那么HashMap是如何扩容的呢?通过查阅源码可以看出...

  • 面试流水(二)

    arraylist和hashmap容易混淆的点 初始化 arraylist初始化默认容量是10,扩容条件是放不下才...

  • HashMap扩容测试(基于java8进行测试)

    结论:初始容量为16的HashMap,当向这个集合中添加第13个键值对时,会触发扩容,扩容后的容量为32 测试代码...

  • HashMap:如何进行扩容?

    在说明hashMap如何进行扩容之前,先说下为什么要进行扩容?是因为hashMap初始化的容量不够用了吗?不是,是...

  • Java HashMap 的扩容因子为什么是 0.75

    所谓的加载因子,也叫扩容因子或者负载因子,它是用来进行扩容判断的。 假设加载因子是0.5,HashMap初始化容量...

  • HashMap&ConcurrentHashMap

    HashMap: 当前容量和装载因子,当数组长度大于当前容量和装载因子的乘积时,HashMap就会扩容。 寻址方式...

  • HashMap学习笔记

    HashMap学习笔记 初始容量在构造HashMap的时候根据预期的entry数量考虑初始容量和负载因子,这样可以...

  • 性能代码收藏

    HashMap扩容 Java HashMap采用了多次无符号位移运算计算容量,返回大于当前容量的符合2^n整型值,...

  • Java集合—HashMap为什么2倍扩容

    本文转载于:原文地址:HashMap初始容量为什么是2的n次幂及扩容为什么是2倍的形式[https://blog....

网友评论

    本文标题:HashMap初始容量和扩容

    本文链接:https://www.haomeiwen.com/subject/zbyetftx.html