总结: 01.ArrayList中维护了一个Object类型的数组elementData(transient Object[] elementData) 02.创建ArrayList对象时 若使用的是无参构造器 则elementData容量为0 第一次添加元素时扩容为10 若再次扩容 则扩容为当前容量的1.5倍 03.创建ArrayList对象时 若使用的是有参构造器 则elementData容量为参数指定容量 扩容时扩容为当前容量的1.5倍(注:存在0-1、1-2的情况) 不可认为 new ArrayList<>() 与 new ArrayList<>(0) 等价 文章末尾处将图解说明 关于修饰elementData数组的transient关键字:被transient关键字修饰的对象不会被序列化 关于扩容后的数组:扩容实际上调用了Arrays.copyOf(elementData, newCapacity)方法 返回了一个新数组
- public ArrayList() {
- this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
- }
- 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);
- }
- }
- public ArrayList(Collection extends E> c) {
- Object[] a = c.toArray();
- if ((size = a.length) != 0) {
- if (c.getClass() == ArrayList.class) {
- elementData = a;
- } else {
- elementData = Arrays.copyOf(a, size, Object[].class);
- }
- } else {
- // replace with empty array.
- elementData = EMPTY_ELEMENTDATA;
- }
- }
- transient Object[] elementData;
-
- private static final Object[] EMPTY_ELEMENTDATA = {};
-
- private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
进入add方法后,将先调用ensureCapacityInternal方法以判断是否需要扩容,若需要则进行扩容,反之则不进行扩容,之后再向elementData数组中添加元素(即向集合中添加元素时,均会检测是否需要进行扩容);参数size + 1将作为minCapacity传入,即集合的最小容量需求
注:size指集合中存放的元素个数
- public boolean add(E e) {
- ensureCapacityInternal(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
进入ensureCapacityInternal方法,将调用ensureExplicitCapacity方法,该方法为判断是否需要进行扩容,并真正调用扩容方法的方法,但传入的参数需要先经过calculateCapacity方法处理
- private void ensureCapacityInternal(int minCapacity) {
- ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
- }
进入calculateCapacity方法,若elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,即集合是通过无参构造创建的, 将minCapacity修改为DEFAULT_CAPACITY,即minCapacity = 10;否则返回传入的minCapacity,不做修改
注:该方法决定了,集合若为无参构造创建,则第一次扩容将被扩容为10
- private static int calculateCapacity(Object[] elementData, int minCapacity) {
- if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
- return Math.max(DEFAULT_CAPACITY, minCapacity);
- }
- return minCapacity;
- }
-
- private static final int DEFAULT_CAPACITY = 10;
进入ensureExplicitCapacity方法,若minCapacity - elementData.length > 0,即集合的最小容量需求大于elementData数组的容量,将调用grow方法进行扩容,否则不进行扩容
注:modCount用于记录集合元素的被修改次数,在许多方法中均被调用
- private void ensureExplicitCapacity(int minCapacity) {
- modCount++;
-
- // overflow-conscious code
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }
进入grow方法,在进行一些简单判断后,调用Arrays.copyOf方法进行扩容;Arrays.copyOf方法将返回一个新的数组,即扩容后的数组实际上和扩容前的数组不是同一个数组,但Arrays.copyOf方法会保留扩容前的数组中的元素,并在扩容的部分填入null
注:oldCapacity + (oldCapacity >> 1)即为oldCapacity + oldCapacity/2,该代码决定了大部分的扩容,扩容后的数组容量为扩容前的1.5倍(存在0-10、0-1、1-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);
- }
不可认为 new ArrayList<>() 与 new ArrayList<>(0) 等价
前者:很显然,扩容后elementData数组容量为10

后者:很显然,扩容后elementData数组容量为1
