JDK8
add()方法
通过无参构造ArrayList之后
当我们add()添加一个元素的时候,先执行ensureCapaCityInternal 并且由于初始化是一个空数组所以size是0,此时方法就是ensureCapaCityInternal(0+1)
然后去执行ensureExplicitCapacity(),这个方法的参数需要先执行calculateCapacity() 并且传入 两个参数 其中minCapacity就是size+1的值也就是1,但同时由于是刚初始化的数组,此时elementData 这个数组是一个空数组并进行判断,返回传入的最小容量和默认容量取大值,那么第一次就会返回10 即默认的容量
ensureExplicitCapacity()方法此时的参数就是10,进入方法minCapacity-elementData.length>0就成立 开始执行扩容grow(minCapacity)操作(初始化添加元素执行第一次扩容)
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容操作
获取旧数组容量0
获取新数组容量 = 旧数组容量+旧数组容量带符号右移一位 = 旧数组容量+旧数组容量除以2 =1.5旧数组容量 第一次也是0
判断新数组容量是否小于的最小容量,如果小于那么最小容量就是新数组的容量(0-10<0)
此时新容量就是10,第一次扩容完毕
add()第二个元素 执行到calculateCapacity()里面发现现在数组容量是10 不满足条件所以不扩容
一直到第10个元素 此时minCapcity是11 elementData.length是10,再次扩容
grow()里获取老容量10 新容量是1.5倍老容量也就是15 新容量此时肯定大于最小容量 所以判断新容量和最大容量哪个大,此时并不大与所以也不执行hugeCapacity
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
其实hugeCapacity就是做了一个容量判断 ,最小容量是否,超过了最大值Integer.MAX_VALUE - 8;超过了的话 他就是Integer的最大值,否则就是Integer.MAX_VALUE - 8;
JDK19
在ArrayList初始化两个版本没有变化,都是有三个构造器
add()
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
elementData[index] = element;
size = s + 1;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
add()里面又调用了一个3参的add(),此时add(e,0,0),初始s=0 elementData.length =0,直接扩容
private Object[] grow() {
return grow(size + 1);
}
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
扩容
第一个元素进来 minCapacity = 1 oldCapacity = 0 直接进入else 创建一个默认大小10的数组
当第二个元素进来,add()里直接在数组上添加元素直到第10个,发现数组大小和元素个数相等,又开始扩容,此时grow()里 oldCapacity = 10 进入if 里面有个 ArraysSupport.newLength()
public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
// preconditions not checked because of inlining
// assert oldLength >= 0
// assert minGrowth > 0
int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
return prefLength;
} else {
// put code cold in a separate method
return hugeLength(oldLength, minGrowth);
}
}
传入10,1,5这三个参数(针对添加第11个元素来说) 此时prefLength = 15(还是扩容1.5),此时直接return prefLength作为扩容大小,调用Arrays.copy(),拷贝数组,Arrays.copy()底层又调用了System.arraycopy()对数组进行拷贝
private static int hugeLength(int oldLength, int minGrowth) {
int minLength = oldLength + minGrowth;
if (minLength < 0) { // overflow
throw new OutOfMemoryError(
"Required array length " + oldLength + " + " + minGrowth + " is too large");
} else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {
return SOFT_MAX_ARRAY_LENGTH;
} else {
return minLength;
}
}