ArrayList中维护了一个Object类型的数组elementData:
trainsient Object[] elementData
其中trainsient的意思就是瞬间的,短暂的,不会被序列化
当创建ArrayList对象时,如果使用的是无参构造器,则初始化elementData的容量为0,第一次添加时,扩容elementData为10,如需再次扩容,则扩容为原来的1.5倍
如果使用的是指定elementData容量大小参数的构造器,则初始容器大小为指定大小,如需再次扩容,则变为原来的1.5倍
底层源码分析(以无参构造器为例):
进入ArrayList的无参构造器:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
再进入DEFAULTCAPACITY_EMPTY_ELEMENTDATA看一下:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
发现DEFAULTCAPACITY_EMPTY_ELEMENTDATA其实就是一个空数组。
list.add()方法调用时的底层源码分析:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
可以看出: ensureCapacityInternal(size + 1); 先确认一下容量是否够用,
elementData[size++] = e;然后在添加元素
进入 ensureCapacityInternal源码:
可以看出,会确定minCapacity,第一次为10
再进入到ensureExplicitCapacity源码:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
其中modCount++:用来记录当前集合被修改的次数,放置多个线程同时修改这个集合
if (minCapacity - elementData.length > 0)
grow(minCapacity);
这个if判断语句的意思就是如果当前容量比应该有的最小容量要小,就说明该扩容了,这个时候执行grow方法才是真正的扩容
进入grow源码:
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);
}
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
oldCapacity >> 1就是除以2的意思,int newCapacity = oldCapacity + (oldCapacity >> 1)就是说newCapacity的大小是oldCapacity的1.5倍
即:第一次newCapacity=10,第二次及以后按照1.5倍扩容,扩容使用的方法是Arrays.copyOf,可以保证原来就有的数据不被覆盖。