底层原理
数据结构
底层数据结构就是一个Object数组
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
继承关系
扩容机制
ArrayList默认初始化大小为:10
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
详细参考:ArrayList扩容机制
-
第一,在add()方法中调用ensureCapacityInternal(size + 1)方法来确定集合确保添加元素成功的最小集合容量minCapacity的值。参数为size+1,代表的含义是如果集合添加元素成功后,集合中的实际元素个数。换句话说,集合为了确保添加元素成功,那么集合的最小容量minCapacity应该是size+1。在ensureCapacityInternal方法中,首先判断elementData是否为默认的空数组,如果是,minCapacity为minCapacity与集合默认容量大小中的较大值。
-
第二,调用ensureExplicitCapacity(minCapacity)方法来确定集合为了确保添加元素成功是否需要对现有的元素数组进行扩容。首先将结构性修改计数器加一;然后判断minCapacity与当前元素数组的长度的大小,如果minCapacity比当前元素数组的长度的大小大的时候需要扩容,进入第三阶段。
-
第三,如果需要对现有的元素数组进行扩容,则调用grow(minCapacity)方法,参数minCapacity表示集合为了确保添加元素成功的最小容量。在扩容的时候,首先将原元素数组的长度增大1.5倍(oldCapacity + (oldCapacity >> 1)),然后对扩容后的容量与minCapacity进行比较:① 新容量小于minCapacity,则将新容量设为minCapacity;②新容量大于minCapacity,则指定新容量。最后将旧数组拷贝到扩容后的新数组中。
扩容的时候,将数组长度增大为原来的1.5倍(oldCapacity + (oldCapacity >> 1)),采用clone()将原数组值复制到新数组
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
线程安全
ArrayList是线程不安全的
为保证线程安全,有三种方法解决:
- 使用线程安全的容器Vector:List list = new Vector<>();
- 使用Collections中的线程安全的容器,例如List objects = Collections.synchronizedList(new ArrayList<>());
- 使用JUC中写时复制类:List list = new CopyOnWriteArrayList<>();