ArrayList扩容源码分析
作者:互联网
ArrayList扩容源码分析
结论
-
实际是维护了一个Object类型的数组(transient Object[] elementData)
transient表示瞬时,表示该属性不会被序列化
-
创建ArrayList时,调用无参构造时
初始elementData容量为0,第一次添加时,扩容至10
如果需要再次扩容时,则扩容为1.5倍
-
创建ArrayList时,调用指定大小的构造器时
初始elementData容量为指定大小
如果需要再次扩容时,则扩容为1.5倍
分析源码:
无参构造时的扩容
无参构造
public ArrayList() {
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 创建了一个空的elementData
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
说明第一次初始化时容量为0
添加方法add()
public boolean add(E e) {
// 扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// 再添加
elementData[size++] = e;
// 100%返回true
return true;
}
确认容量ensureCapacityInternal()
protected transient int modCount = 0;
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// ensureCapacityInternal()
// 此时参数为size + 1
private void ensureCapacityInternal(int minCapacity) {
// 调用函数
// ensureExplicitCapacity()
// 将calculateCapacity(elementData, minCapacity)的返回值作为参数
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// calculateCapacity()
// 用于确定一个minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 如果elementData等于空
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 返回一个DEFAULT_CAPACITY 和 minCapacity比较出的最大值
// private static final int DEFAULT_CAPACITY = 10;
// 也就是说minCapacity<10时,返回的是10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
// minCapacity>10时,返回的是minCapacity
return minCapacity;
}
// ensureExplicitCapacity()
// 此时minCapacity为calculateCapacity()返回值
// size+1<10时,返回的是10
// size+1>10时,返回的是size+1
private void ensureExplicitCapacity(int minCapacity) {
// 记录当前集合被修改的次数
// 多线程修改时会抛出异常
modCount++;
// overflow-conscious code
// 当minCapacity大于当前elementData长度时
if (minCapacity - elementData.length > 0)
// 扩容
// 调用grow()
// 参数为minCapacity
grow(minCapacity);
}
// grow()
private void grow(int minCapacity) {
// overflow-conscious code
// elementData数组长度
// 第一次进来是0
int oldCapacity = elementData.length;
// 用elementData数组长度+elementData数组长度右移一位(正数是相当于除以2)赋给新容器
// 也就是原来elementData数组长度的1.5倍
// 第一次是0
// 第一次没有真正的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果minCapacity比newCapacity大
// 第一次0 - 10 < 0
if (newCapacity - minCapacity < 0)
// 那就将minCapacity赋给newCapacity
// 第一次newCapacity为10
newCapacity = minCapacity;
// 如果newCapacity 比 MAX_ARRAY_SIZE大
// @Native public static final int MAX_VALUE = 0x7fffffff;
// private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// MAX_ARRAY_SIZE 是 0x7fffffff - 8
// 2的31次方-1-8
// newCapacity比最大容量还大的话
// 一般不会
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 比最大容量还大的话调用hugeCapacity()
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 正常情况调用Arrays.copyOf()
// 通过拷贝达到给elementData赋值newCapacity长度的效果
elementData = Arrays.copyOf(elementData, newCapacity);
}
// grow()结束到:
// ensureExplicitCapacity()结束到:
// ensureCapacityInternal()结束到add():
public boolean add(E e) {
// 扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// 赋值
elementData[size++] = e;
// 100%返回true
return true;
}
// add()结束
指定大小的构造器时的扩容
有参构造
public ArrayList(int initialCapacity) {
// 如果参数 > 0
if (initialCapacity > 0) {
// 创建一个长度为参数的Object[]赋给elementData
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 如果参数为0
// private static final Object[] EMPTY_ELEMENTDATA = {};
// 赋值空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 负数抛一个异常
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
add()
public boolean add(E e) {
// 扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// 再添加
elementData[size++] = e;
// 100%返回true
return true;
}
不同在扩容的判断
private void ensureCapacityInternal(int minCapacity) {
// 调用函数
// ensureExplicitCapacity()
// 将calculateCapacity(elementData, minCapacity)的返回值作为参数
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// calculateCapacity()
// 用于确定一个minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 如果elementData等于空
// 此时不为空
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 不走这一步
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
// 返回的是size+1
return minCapacity;
}
// ensureExplicitCapacity()
// 此时minCapacity为calculateCapacity()返回值
// 返回的是size+1
private void ensureExplicitCapacity(int minCapacity) {
// 记录当前集合被修改的次数
// 多线程修改时会抛出异常
modCount++;
// overflow-conscious code
// 当minCapacity大于当前elementData长度时
// 初始够用就不扩,不够用就进
if (minCapacity - elementData.length > 0)
// 扩容
// 调用grow()
// 参数为minCapacity
grow(minCapacity);
}
// grow()
private void grow(int minCapacity) {
// elementData数组长度
int oldCapacity = elementData.length;
// 用elementData数组长度+elementData数组长度右移一位(正数是相当于除以2)赋给新容器
// 也就是原来elementData数组长度的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果minCapacity比newCapacity大
if (newCapacity - minCapacity < 0)
// 那就将minCapacity赋给newCapacity
newCapacity = minCapacity;
// 如果newCapacity 比 MAX_ARRAY_SIZE大
// newCapacity比最大容量还大的话
// 一般不会
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 比最大容量还大的话调用hugeCapacity()
newCapacity = hugeCapacity(minCapacity);
// 正常情况调用Arrays.copyOf()
// 通过拷贝达到给elementData赋值newCapacity长度的效果
elementData = Arrays.copyOf(elementData, newCapacity);
}
// grow()结束到:
// ensureExplicitCapacity()结束到:
// ensureCapacityInternal()结束到add():
public boolean add(E e) {
// 扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// 赋值
elementData[size++] = e;
// 100%返回true
return true;
}
// add()结束
标签:扩容,int,ArrayList,elementData,newCapacity,private,minCapacity,源码,size 来源: https://www.cnblogs.com/coderDreams/p/15925898.html