这里扩容指的是无参构造初始化时的场景。对于指定集合长度的构造函数初始化时,初始容量为指定长度,容量不够时再扩容为原来的 1.5 倍。java
下面主要介绍无参构造初始化时的场景。数组
参数定义:安全
transient Object[] elementData; // 实际存储数据的数组缓冲区 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 初始数组
默认初始化很是简单,调用无参构造器,初始化一个空数组。真正扩容的逻辑在每次添加元素执行。函数
/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
添加方法:this
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
size:ArrayList 的长度,可用 List#size() 获取线程
添加方法一共作了两件事:3d
添加元素不用多说,向数组中的下一个位置插入便可。下面着重介绍容量判断的逻辑:code
1. 判断容量大小对象
首先判断当前集合容量大小是否足够,若是不够就调用扩容方法 grow(int minCapacity)。blog
// 确保集合能够添加下一个元素 minCapacity:当前须要的最小容量 private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // 计算添加元素须要的最小容量 private static int calculateCapacity(Object[] elementData, int minCapacity) { // 若是当前集合为空,判断所需最小容量和默认容量大小,返回较大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } // 确保集合能够知足须要的最小容量 private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
2. 扩容方法
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
首先初始化一个 ArrayList,向里面循环添加 11 个元素。下面针对于第一次添加和第11次添加分别查看 数组初始化 和 数组扩容的逻辑。
public static void main(String[] args) { List<string> list = new ArrayList<>(); for (int i = 0; i < 11; i++) { list.add("items"); } }
ArrayList 初始化后,底层会初始化一个空的对象数组 (elementData),长度 (size) 为 0。当第一次添加元素时,会将其初始化为一个长度为 10 的数组。下面看第一次添加元素的流程:
1.进入添加方法 add(E e)
2.判断容量大小
3.计算所需最小容量
当前数组为空数组,因此if 条件成立,DEFAULT_CAPACITY = 10,minCapacity = 1;
当前方法返回 10;
4.判断数组是否扩容
elementData 当前为空数组,length = 0;minCapacity 为上一步返回的 10;因此此处会调用扩容方法 grow()
5.数组扩容(初始化数组)
这里会根据上面指定的默认容量 10 来给数组扩容。
6.添加元素
根据以前程序的运行,集合保存数据的数组在第一次添加元素时扩充容量为 10,因此在第 11 次添加元素时就会调用扩容的逻辑。
一、add() 方法
minCapacity = size + 1 = 11;
二、判断容量大小
三、计算所需最小容量
非第一次 直接返回
四、判断是否扩容
所需最小容量大于数组长度,调用扩容方法。
五、扩容
六、添加元素