首先来看一张图。
ArrayList实现了List接口,对于List集合类来说:
- List集合类中元素有序(即添加和取出顺序一致),且可重复。
- List集合中的每个元素都有其对应的顺序索引,即支持索引。
- List容器中的元素可以根据其对应的整数型的序号进行存取。
所以ArrayList满足这些用法。
ArrayList的注意事项:
- 可以加入多个null
- 是用数组进行存储的
- ArrayList基本等同于Vector,但ArrayList线程不安全(执行效率高),在多线程情况下不应使用ArrayList
ArrayList源码分析:
1. ArrayList中维护了一个Object类型的数组elementData
transient Object[] elementData;
2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
第一次添加,则扩容elementData为10
public boolean add(E e) {
ensureCapacityInternal(size + 1); //先确认是否要扩容
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// minCapacity是当前集合所需的最小空间
ensureExplicitCapacity(
calculateCapacity(elementData,minCapacity)
);
} //先进入calculateCapacity 方法,
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //第一次添加,空数
return Math.max(DEFAULT_CAPACITY, minCapacity); // (10, 1) 所以返回10
}
return minCapacity;
}
private static final int DEFAULT_CAPACITY = 10;
如果需要再次扩容,则扩容elementData为1.5倍
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //记录当前集合被修改的次数 // overflow-conscious code
if (minCapacity - elementData.length > 0)
//如果elementData大小不够,就调用grow方法真的扩容
grow(minCapacity);
}
//真的扩容
private void grow(int minCapacity) { // overflow-conscious code
int oldCapacity = elementData.length;//由于第一次oldCapacity为0,所以不会使用1.5倍扩容机制
//第二次及其以后,如需扩容则按照1.5倍括
int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容为1.5倍
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);
}
3. 如果使用的是指定大小的构造器,则初始elementData容量为指定大小
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
如果需要扩容,则直接扩容elementData为1.5倍