ArrayList重点分析

这是我参与11月更文挑战的第19天,活动详情查看:2021最后一次更文挑战

初始化

无参数初始化:
     public ArrayList() {
         // 赋值默认空数组
         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
     }
复制代码
带参数初始化:
     /**
      * 根据给定容量初始化
      */
     public ArrayList(int initialCapacity) {
         if (initialCapacity > 0) {
             // 参数大于0情况下直接创建该大小数组
             this.elementData = new Object[initialCapacity];
         } else if (initialCapacity == 0) {
             this.elementData = EMPTY_ELEMENTDATA;
         } else {
             throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
         }
     }
 ​
     /**
      * 根据给定集合初始化
      */
     public ArrayList(Collection<? extends E> c) {
         elementData = c.toArray();
         if ((size = elementData.length) != 0) {
             // c.toArray might (incorrectly) not return Object[] (see 6260652)
             if (elementData.getClass() != Object[].class)
                 elementData = Arrays.copyOf(elementData, size, Object[].class);
         } else {
             // replace with empty array.
             this.elementData = EMPTY_ELEMENTDATA;
         }
     }
复制代码

新增、扩容机制

新增机制

image-20211121163200915.png

  1. 确保数组长度足够
  2. 将元素追加到数组现有最后一位元素后面
  3. 容器大小+1

image-20211121163225080.png 确保容量足够,如果当前数组长度不大于所需的最小长度,触发扩容操作

扩容机制

image-20211121163412000.png 核心:新数组长度 = 旧数组长度 + 旧数组长度/2(向下取整)

整体描述新增扩容过程
  1. 确保数组长度足够存储接下来的一位元素。

    1. 计算出所需要的最小容量,如果大于现有的数组长度,开始扩容。
    2. 扩容细节:计算出新的数组长度(如果new capacity < 最小所需长度,将最小所需数组长度赋值);创建新数组,完成元素迁移工作。
  2. 容器存储元素大小 + 1,将元素添加到数组中元素尾巴上。

批量删除

从ArrayList中删除另一个集合中的所有元素

双指针法:定义两个变量r、w,遍历elementData,以r记录遍历元素位置,w记录重新赋值元素的位置

遍历结束后,将w位置之后的元素全部置为null,表示删除元素。

     int r = 0, w = 0;
     for (; r < size; r++)
         if (!c.contains(elementData[r]))
             elementData[w++] = elementData[r];
 ​
     for (int i = w; i < size; i++)
         elementData[i] = null;
复制代码

Guess you like

Origin juejin.im/post/7032957978563051534