使用过ArrayList或者背过面试题的小伙伴都知道ArrayList
的初始容量为10
。
但这个答案不完全正确,在jdk1.2
到jdk1.6
中的ArrayList
的源码中,在构造方法上的确是创建了一个初始容量为10的容器。
摘录jdk_1.6
的源码,1.2到1.6
都是直接创建一个长度为10的数组
但是在jdk_1.7
中的源码是这样写的
调用构造方法时,如下
说明从jdk_1.7
开始,当你进行new ArrayList();创建的是一个空数组
初始容量就不是10了,而是一个空数组
从jdk_1.2
开始到jdk_1.6
,ArrayList
都是直接创建了一个长度为10
的数组。
是否有疑问jdk1.7
初始容量为0
,它是怎么进行扩容的?
在jdk_1.7
中的ArrayList
定义了一个常量这个值就是10
这个常量在进行扩容的时候,会和当前容器的最小容量进行比较,取最大的作为新容器的容量
例如当你第一次调用add进行添加元素的时候,会触发扩容
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
进入ensureCapacityInternal(size + 1);
,一开始是一个空容器所以size=0
传入的minCapacity=1
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
会发现minCapacity
被重新赋值为10 (DEFAULT_CAPACITY=10
)
传入ensureExplicitCapacity(minCapacity);
这时minCapacity=10
下面是方法体:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
modCount++
是在父类AbstarctList
中,
后又调用了扩容grow(10)
private void grow(int minCapacity) {
int oldCapacity = elementData.length;// oldCapacity = 0
int newCapacity = oldCapacity + (oldCapacity >> 1);// newCapacity = 0
if (newCapacity - minCapacity < 0) // true
newCapacity = minCapacity;// newCapacity = 10
if (newCapacity - MAX_ARRAY_SIZE > 0) // false , MAX_ARRAY_SIZE =Integer.MAX_VALUE - 8;
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);//创建了长度为10的数组
}
这是jdk1.7中的扩容机制代码
其中int newCapacity = oldCapacity + (oldCapacity >> 1);
就是面试过程中经常提问到的,1.5倍
原来数组的长度
再则ArrayList是允许自己设置初始容量的,调用带参数的构造方法即可,然后以这个初始容量按照1.5倍
当前设置的初始容量进行扩容。
另外关于ArrayList的文章请看我其它几篇博客:
一文搞定ArrayList、LinkedList、HashMap、HashSet -----源码解读之ArrayList
你知道ArrayList哪几种情况下会报java.util.ConcurrentModificationException吗?