ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

《ArrayList的初始化和扩容源代码解读》

《ArrayList的初始化和扩容源代码解读》

1. 构造方法的源代码解读

(1)无参构造

public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
  • 将elementData初始化为一个空数组;
  • DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是一个空数组({}),用于标记“尚未真正初始化”;
  • 此时底层数组长度为 0,不会分配默认容量 10;
  • 真正的容量(10)会在第一次调用 add() 时通过扩容机制分配

(2)指定初始容量的构造方法

public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
  • 初始容量> 0:创建指定大小的数组
  • 初始容量 = 0:使用空数组EMPTY_ELEMENTDATA
  • 初始容量< 0:抛出IllegalArgumentException异常

(3)使用集合构造

public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
  • 将集合转为Object数组,赋值给elementData
  • 处理c.toArray()可能返回非Object[]类型的情况
  • 如果集合为空,初始化为空数组

2. add()方法的源代码解读

public boolean add(E e) { ensureCapacityInternal(size + 1); //确保容量足够 elementData[size++] = e; //添加元素 return true; }

计算最小所需容量

private static int calculateCapacity(Object[] elementData, int minCapacity) { //如果是无参构造的默认空数组,直接返回默认容量10 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; }
  • 若是首次添加(底层数组为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,也就是为空),则 minCapacity 至少为 DEFAULT_CAPACITY(即 10);

确保底层数组有足够的内部容量

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

接着调用 ensureExplicitCapacity(),判断是否需要扩容

private void ensureExplicitCapacity(int minCapacity) { modCount++; // 最小所需容量 > 底层数组当前长度 → 容量不足,触发扩容 if (minCapacity - elementData.length > 0) grow(minCapacity); }

3. grow()方法的源代码解读

private void grow(int minCapacity) { // 获取当前底层数组的旧容量 int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容1.5倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity;
  • 当1.5倍扩容后仍小于所需最小容量时

  • 直接使用所需最小容量

if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity);//处理大容量 elementData = Arrays.copyOf(elementData, newCapacity); }

MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
超过则调用 hugeCapacity();

返回列表