• ArrayList的扩容机制


      ArrayList是List接口的实现类,它是支持根据需要而动态增长的数组。java中标准数组是定长的,在数组被创建之后,它们不能被加长或缩短。这就意味着在创建数组时需要知道数组的所需长度,但有时我们需要动态程序中获取数组长度。ArrayList就是为此而生的。

      因此,了解它的扩容机制对使用它尤为重要。

      ArrayList扩容发生在add()方法调用的时候,下面是add()方法的源码:

        public boolean add(E e) {
           //扩容
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }

      根据意思可以看出ensureCapacityInternal()是用来扩容的,形参为最小扩容量,进入此方法后:

    private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

       通过方法calculateCapacity(elementData, minCapacity)获取:

        private static int calculateCapacity(Object[] elementData, int minCapacity) {
            //如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            return minCapacity;
        }

       ensureExplicitCapacity方法可以判断是否需要扩容:

     private void ensureExplicitCapacity(int minCapacity) {
              modCount++;
     
              // 如果最小需要空间比elementData的内存空间要大,则需要扩容
              if (minCapacity - elementData.length > 0)
                  //扩容
                  grow(minCapacity);
          }

       接下来重点来了,ArrayList扩容的关键方法grow():

      private void grow(int minCapacity) {
              // 获取到ArrayList中elementData数组的内存空间长度
              int oldCapacity = elementData.length;
             // 扩容至原来的1.5倍
             int newCapacity = oldCapacity + (oldCapacity >> 1);
             // 再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,
              // 不够就将数组长度设置为需要的长度
             if (newCapacity - minCapacity < 0)
                 newCapacity = minCapacity;
             //若预设值大于默认的最大值检查是否溢出
             if (newCapacity - MAX_ARRAY_SIZE > 0)
                 newCapacity = hugeCapacity(minCapacity);
             // 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间
             // 并将elementData的数据复制到新的内存空间
             elementData = Arrays.copyOf(elementData, newCapacity);
         }

     从此方法中我们可以清晰的看出其实ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。

    到此扩容就基本完成了。

  • 相关阅读:
    事务(十四)
    事务(十三)
    事务(十二)
    事务(十一)
    事务(十)
    try中定义输入流报错:Try-with-resources are not supported at language level '5'
    IDEA新建时没有java class选项
    Hex编码
    Git Bash安装及常规使用
    PostgreSQL数据库
  • 原文地址:https://www.cnblogs.com/dengrongzhang/p/9371551.html
Copyright © 2020-2023  润新知