jdk1.8为例
1.ArrayList类构造方法
a.有参构造
//initcalCapacity指定的初始化容量
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//初始化指定的
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//==0的话 默认容量是10
this.elementData = EMPTY_ELEMENTDATA;
} else {
//<0的话会报异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
b.无参构造
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
无参构造指定底层elementData数组指向DEFAULTCAPACITY_EMPTY_ELEMENTDATA数组
有参构造指定底层elecmentData数组指向EMPTY_ELEMENTDATA数组
他们两个都是空数组
/**
* 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.
* //用于默认大小的空实例的共享空数组实例。
* 我们将其与 EMPTY_ELEMENTDATA 区分开来,
* 以了解在添加第一个元素时要膨胀多少。
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
都是空数组,只是DEFAULTCAPACITY_EMPTY_ELEMENTDATA用来连接在添加第一个元素时要膨胀多少。
2.add(E e)方法
public boolean add(E e) {
//确保内部容量
ensureCapacityInternal(size + 1); // Increments modCount!!
//在底层数组默认添加元素
elementData[size++] = e;
//返回true添加成功
return true;
}
测试:添加一个元素执行哪些操作
@Test
public void test(){
ArrayList list = new ArrayList<>();
list.add(1);
}
调用栈:

具体的方法
计算容量的方法
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果是通过无参构造方法构造的
//返回默认容量10和最小容量(size+1)的最大值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果是有参构造 直接返回size+1
return minCapacity;
}
//确保容量的方法
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//确保显示容量的方法
private void ensureExplicitCapacity(int minCapacity) {
//modCount由该类迭代器所使用,如果此字段发生了更改,迭代器在使用next(),remove()方法时抛出
//ConcurrentModificationException异常
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//扩容方法
grow(minCapacity);
}
容量不足时,需要扩容。
grow为扩容方法。
3.扩容代码
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新容量是 等于 旧容量+旧容量的0.5倍
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);
}
新容量是 等于 旧容量+旧容量的0.5倍
如果新容量超过了最大值则扩容值为整型数组最大值
elementData = Arrays.copyOf(elementData, newCapacity)通过底层的复制方法将原有数据复制过来
测试扩容次数代码:
@Test
public void test(){
int oldCapacity = 10;
int newCapacity = 0;
int growCount=0;
while(newCapacity < 1000){
newCapacity = oldCapacity + oldCapacity / 2;
oldCapacity = newCapacity;
growCount++;
}
System.out.println("容量达到1000需要扩容"+growCount);
newCapacity = 0;
oldCapacity=10;
growCount = 0;
while(newCapacity < 10000){
newCapacity = oldCapacity + oldCapacity / 2;
oldCapacity = newCapacity;
growCount++;
}
System.out.println("容量达到10000需要扩容"+growCount);
newCapacity = 0;
oldCapacity=10;
growCount = 0;
while(newCapacity < 100000){
newCapacity = oldCapacity + oldCapacity / 2;
oldCapacity = newCapacity;
growCount++;
}
System.out.println("容量达到100000需要扩容"+growCount);
newCapacity = 0;
oldCapacity=10;
growCount = 0;
while(newCapacity < 1000000){
newCapacity = oldCapacity + oldCapacity / 2;
oldCapacity = newCapacity;
growCount++;
}
System.out.println("容量达到1000000需要扩容"+growCount);
}
结果为:
容量达到1000需要扩容12
容量达到10000需要扩容18
容量达到100000需要扩容23
容量达到1000000需要扩容29
根据实际情况,分配一个初始化的容量很有必要的
容量太大,数据增长缓慢,浪费内存。
容量太小,扩容次数变多,影响性能。
本文详细解析了Java ArrayList的构造方法,特别是有参和无参构造的区别,以及add(E e)方法如何确保容量。在添加元素时,ArrayList会进行扩容,其扩容策略是旧容量加上旧容量的一半。通过测试,展示了不同初始容量下达到特定大小所需扩容的次数,强调了合理设置初始化容量对于避免过多扩容、提升性能的重要性。
1万+





