一、前言
ArrayList就不赘述了,线程不安全、底层数据结构是数组、查询快、增删慢等等
List list = Collections.synchronizedList(new ArrayList(...)); //这样可以实现线程安全
二、源码分析
ArrayList的初始容量?ArrayList的扩容规则?
/**
* 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.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
......
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
上面代码可以看出在初始化的时候没有指定ArrayList大小,默认容量elementData = 0
第一次调用add后,长度变为10,如下面代码所示:
public boolean add(E e) {
// 调用第一次,size=0
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// 第一次传过来的minCapacity=1 由上面可知 默认elementData=0
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 0 == 0 ,进入循环
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 取10 和 1 的最大值,返回10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 此时minCapacity=10
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 10-0>0 走grow
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// minCapacity = 10
private void grow(int minCapacity) {
// 此时elementData.length = 0
int oldCapacity = elementData.length;
// 0 位运算 右移一位还是 0
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 0-10<0 进入循环
if (newCapacity - minCapacity < 0)
// newCapaticy = 10;
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);
}
public boolean add(E e) {
ensureCapacityInternal(size + 1);
// elementData[0] = e
elementData[size++] = e;
return true;
}
当数组首次扩容的10个空间用完需要进行扩容时,会第二次走grow方法来扩容(扩容规则为原来容量的1.5倍,如果扩容的长度不够,则数组最终长度为原长度+新元素长度之和)
// 当长度满10个,第11个元素进来时,minCapacity=11
private void grow(int minCapacity) {
// oldCapacity = 10
int oldCapacity = elementData.length;
// 1010 >> 1 == 101 = 5 向右位移一位是原来的一半,加上原来后正好是原来的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果扩容的长度不够,则把当前元素的长度给新数组长度
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果扩容的长度够,则进行扩容
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
小结:ArrayList初始大小为10,每次1.5倍进行扩容;它的底层是用数组实现的,所以查询速度相对LinkedList要快。