Fork me on GitHub

集合的初始容量

一直以来记得都是ArrayList的底层是数组,初始容量为10,但是今天群里有人说了初始容量是0,当第一add方法时才会变成10,我没仔细看jdk源码,只看到ArrayList构造方法上注释为,初始容量为10,构造一个初始容量为10的空list。以为默认就是10,经过仔细分析才知道当第一次添加元素时才会扩容为10。

1
2
3
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
1
2
3
4
5
public boolean add(E e) {
ensureCapacityInternal(size + 1); //首先调用ensureCapacityInternal方法,参数为0+1=1
elementData[size++] = e;
return true;
}
1
2
3
4
private void ensureCapacityInternal(int minCapacity) {
//传入的参数为1,故minCapacity为1,将elementData=0和minCapacity=1传入calculateCapacity方法,然后调用ensureExplicitCapacity方法
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
1
2
3
4
5
6
7
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//传来的参数elementData=0,minCapacity=1,故elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA为true,然后返回(DEFAULT_CAPACITY, minCapacity)中最大的数,是DEFAULT_CAPACITY为10。
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
1
2
3
4
5
6
7
8
9
private void ensureExplicitCapacity(int minCapacity) {
//参数minCapacity为10
modCount++;

// overflow-conscious code
//minCapacity为10减去elementData.length>0,调用grow方法,参数为10
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
1
2
3
4
5
6
7
8
9
10
11
12
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //oldCapacity为0
int newCapacity = oldCapacity + (oldCapacity >> 1);//newCapacity为0
if (newCapacity - minCapacity < 0) //0-10<0
newCapacity = minCapacity; //将10赋值给newCapacity
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);
}
~~~然后数组复制就不说了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test
{
public static void main(String[] args)
{
ArrayList arrayList = new ArrayList();
System.out.println("capacity: "+getCapacity(arrayList)+" size: "+arrayList.size());
arrayList.add("a");
System.out.println("capacity: "+getCapacity(arrayList)+" size: "+arrayList.size());
}
public static int getCapacity(ArrayList arrayList)
{
try {
Field elementDataField = ArrayList.class.getDeclaredField("elementData");
elementDataField.setAccessible(true);
return ((Object[]) elementDataField.get(arrayList)).length;
} catch (Exception e)
{
e.printStackTrace();
return -1;
}
}
}

输出结果:
capacity: 0 size: 0
capacity: 10 size: 1

同理好像map集合也是这样,当创建不用的时候,容量为空可以省空间,这也是懒加载机制。用的时候才增加到容量为10.