-
关于ArrayList的构造函数
1.无参构造,初始化一个容量为0的空数组。
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}为ArrayList的成员变量。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
}
2.带初始容量的有参构造。应注意elementData是一个Object类型的数组,是ArrayList的成员变量。
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {//参数大于0,则创建一个容量为initialCapacity 的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {//参数等于0,则创建一个容量为0的数组
this.elementData = EMPTY_ELEMENTDATA;
} else {//参数小于0,抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
3.参数为Collection元素的列表。
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();//将集合c转化为数组
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
-
扩容机制
首先大致浏览一下底层源码扩容的整体流程:
//调用add进行添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//add调用ensureCapacityInternal
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//calculateCapacity方法
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//ensureExplicitCapacity
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//核心扩容代码块
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创建对象时,未指定集合大小,则底层数组初始化长度为0,若已经指定合法长度,则初始长度为指定的长度。
这里详述创建对象时,未指定集合大小时的情况:
当第一次调用add方法时,则创建一个长度为10的数组,即将数组长度扩容到10。DEFAULT_CAPACITY的值为10.
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//elementData 为空数组
return Math.max(DEFAULT_CAPACITY, minCapacity);//则返回DEFAULT_CAPACITY, minCapacity之间的最大值
}
return minCapacity;
}
添加第一个元素时,elementData.length为0,则会进入grow方法。
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//修改次数
if (minCapacity - elementData.length > 0)//添加第一个元素时,minCapacity=10,elementData.length=0
grow(minCapacity);//实现真正的扩容
}
grow方法中,新容量每次扩大到原来容量的1.5倍,若扩容之后依然不够,则将真正所需要的容量(minCapacity)作为扩容的大小。
private void grow(int minCapacity) {//参数minCapacity=10
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量为旧容量的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;//第一次添加元素时,newCapacity扩容到10
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);
}
当添加第二个元素时,minCapacity=2,elementData.length=10,此时不需要进入grow()
......
当添加第11个元素时,minCapacity=11,elementData.length=10,此时11-10>0满足if条件判断,进入grow(),进行扩容