ArrayList是使用频率较高的容器,实现较为简单。内部主要靠一个可自动扩容的对象数组来维持
transient Object[] elementData;// 非私有简化嵌套类访问
可以通过构造函数指定初始容量,也可以不指定(默认初始容量为10);
//指定初始容量
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);
}
}
//使用默认容量,在首次进行add时进行扩容
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
当每次通过add添加元素时会调用ensureCapacityInternal(size + 1);
private void ensureCapacityInternal(int minCapacity)
{
//判断是否使用默认容量且为首次添加元素,计算需扩容大小
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
{
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//确认需要扩容的容量大于数组长度
ensureExplictCapacity(minCapacity);
}
//扩容机制
private void grow(int minCapacity)
{
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + oldCapacity >> 1;
if (newCapacity - minCapacity < 0)
{
newCapacity = minCapacity;
}
if (newCapacity - MAX_ARRAY_SIZE > 0)
{
hugeCapacity(newCapacity);
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
可以看出,当容量不足时,ArrayList1.5倍扩容,当使用addAll(Collection<? extends E> c)添加时,若1.5倍扩容不满足时,则使用size+c.toArray().length扩容。
ArrayList支持指定位置的赋值,通过set(int,E)和add(int,E)方法,在执行这些操作时都需要对范围进行检查,同理还有获取和移除指定位置的元素。
elementData数组是transient的,这表明系统默认序列化执行时跳过该数组。取而代之的是,ArrayList提供了writeObject和readObject方法来自定义写入和读取该数组的方式。为什么不使用elementData来序列化,因为elementData的长度通常大于size,这样做是为了确保只序列化实际存储的元素
private void writeObject(ObjectOutputStream s)
throws IOException
{
int exceptedModCount = modCount;
s.defaultWriteObject();
s.writeInt(size);
for (int i = 0; i < size; i++)
{
s.writeObject(elementData[i]);
}
if (modCount != exceptedModCount)
{
throw new ConcurrentModificationException();
}
}
private void readObject(ObjectInputStream s) throws IOException,
ClassNotFoundException
{
elementData = EMPTY_ELEMENTDATA;
s.defaultReadObject();
s.readInt();
if (size > 0)
{
ensureCapacityInternal(size);
Object[] a = elementData;
for (int i = 0; i < size; i++)
{
a[i] = s.readObject();
}
}
}
作为容器的共性,ArrayList提供迭代器,并通过内部类定义了Itr、ListItr这两个迭代器。
ArrayList的排序
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
ArrayList底层为数组,在随机添加、插入和删除,需要对元素进行移动效率低,但是对于随机访问效率很高;适用于访问多,对元素操作少的场景。