ArrayList集合详解
1、简介
- ArrayList继承自AbstractCollection类,实现了List接口,底层基于数组实现了容量大小的动态变化,允许null值存在,支持快速访问、复制和序列化。
//默认初始容量大小为10
private static final int DEFAULT_CAPACITY = 10;
//从有参构造函数初始化
private static final Object[] EMPTY_ELEMENTDATA = {};
//从空的构造函数初始化
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//真实数组
transient Object[] elementData;
//实际元素个数
private int size;
//被定义在AbstractCollection中,用来记录List操作次数,主要是防止迭代过程中内容被修改
protected transient int modCount = 0;
//每次添加新元素就把size加1,记录数组中保存元素的个数
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//数组扩容,每次扩容为原来容量的1.5倍。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
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);
}
//最大存储为Integer.MAX_VALUE
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
//把指定元素后面所有元素,利用System.arraycopy方法向前整体移动一位
//然后把最后一个元素值指定为null,这样GC就会回收。
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
2、优缺点
2.1、优点
- ArrayList允许值为空,也允许重复数据,但是ArrayList内存是有序的。
- 底层以数组实现,所以查询get特别快
- ArrayList顺序添加元素特别快。
2.2、缺点
- 删除元素和插入元素时,涉及到元素复制,要复制的元素很多,那么消耗的性能就会很多。
- 线程非安全的,不过可以使用一下两种方法实现线程安全
-
- 使用Vector代替ArrayList,Vector就是ArrayList的线程安全版本;Vector可以指定增长因子,如果不指定增长因子,那么就是原数组的2倍。
- 使用Collections.synchronized(list),使ArrayList线程线程安全的。