public static void main(String[] args) {
Collection col = new ArrayList();
for (int i = 0; i <= 10; i++) {
col.add(i);
}
}
//对上面这段代码进行调试 来探究扩容机制。
/**
* 首先进入一个空参构造器,会给ArrayList维护的数组elementData[]
* 分配一个空间DEFAULTCAPACITY_EMPTY_ELEMENTDATA(默认容量为空的数组),但是没有分配容量大小。
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 然后进行添加,添加之前会调用ensureCapacityInternal方法确实是否扩容
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* ensureCapacityInternal中接收到数组需要的最小容量minCapacity 即已有的数据长度+需要新增的数据长度
* 首先调用calculateCapacity,看数组是不是空参构造器构造的空数组
*/
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* 此方法判断数组是不是空参构造器构造的空数组,若是就看最少需要容量与默认第一次扩容的容量(10)谁大
* 扩多的那个 不然不能满足需求
*
* 在第二次扩容时,elementData不是空了 直接就返回需要的最小容量
* 此方法我觉得作用就是检验elementData是不是空数组,若是空数组,就计算第一次数组的容量该赋多少
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);//DEFAULT_CAPACITY == 10
}
return minCapacity;
}
/**
* 这里接收到的minCapacity才是真正的最小容量所需,也是真正判断是否需要扩容的地方
* 如果最小需要容量,大于了数组长度 则调用grow方法扩容
*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//是一个transient修饰的变量,不可序列化,作用就是记录检查扩容的次数,以防止多线程同时操作。
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 真正扩容的地方,
* 先获取数组长度,然后将数组长度赋给oldCapacity,使其变为1.5倍
* 若数组长度是0,那么计算结果也是0,
* 所以就会先将newCapacity - minCapacity比较防止扩容0个
* Arrays.copyOf()会将elementData的数据之前的保留下来,之后完成扩容
* 之后在add()中就添加数据 elementData[size++] = e;
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//对于非负数来说,右移移位相当于除以2,
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 就会赋容量为空的数组对象,接下来和无参构造一样的添加等
* 若初始化大小大于0 那么就会直接分配一个这么大的空数组对象
* 若初始化大小小于0 那么就会抛出异常
*/
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);
}
}
因此可以得出结论:
原文:https://www.cnblogs.com/jtStudy/p/14613334.html