目录
ArrayList是一种以数组实现的List,与数组相比,它具有动态扩展的能力,因此也可称之为动态数组。
继承体系
- ArrayList实现了List, RandomAccess, Cloneable, java.io.Serializable等接口。
- ArrayList实现了List,提供了基础的添加、删除、遍历等操作。
- ArrayList实现了RandomAccess,提供了随机访问的能力。
- ArrayList实现了Cloneable,可以被克隆。
- ArrayList实现了Serializable,可以被序列化
源码解析
1.属性
//默认初始容量
private static final int DEFAULT_CAPACITY = 10;
//空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//空数组,new ArrayList()时使用,添加第一个元素的时候会重新初始为默认容量大小
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//保存要存储元素的数组
transient Object[] elementData;
//数组长度
private int size;
2.构造方法
无参构造
public ArrayList() {
//调用默认空数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
int型参数的构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//如果传入的值大于0,则直接按照传入的大小来构造数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//等于0,则赋值空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
Collection型参数构造方法
public ArrayList(Collection<? extends E> c) {
//把传入集合中的数组赋值给elementData
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
//判断elementData的类型是否为Object[],如果不是重新把elementData拷贝为Object[]类型
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
//传入的是一个空集合,则把elementData赋值为默认空数组
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
3.添加元素
add(E e)方法
源码:
public boolean add(E e) {
//检查是否需要扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//把新元素添加到数组末尾
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//如果ArrayList中elementData 为null则需要创建数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//取传入长度与默认数组长度较大的一个作为创建数组的长度
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
//数组被修改所以+1
modCount++;
// overflow-conscious code
//要存储的长度大于数组长度则需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新容量为旧容量的1.5倍
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);
}
添加元素很简单就是直接判断是否扩容,然后把元素添加到队尾。
add(int index, E element)
public void add(int index, E element) {
//判断传入索引是否合法
rangeCheckForAdd(index);
//检测是否需要扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//将index位置的元素后移一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
3.获取元素
ArrayList中获取元素只有一个方法就是get,源码:
public E get(int index) {
//检测索引是否超出范围
rangeCheck(index);
//返回对应索引位置的元素
return elementData(index);
}
4.删除元素
remove(int index)通过索引删除
public E remove(int index) {
rangeCheck(index);
modCount++;
//获取对应索引位置的元素
E oldValue = elementData(index);
//计算要移动元素的个数
int numMoved = size - index - 1;
if (numMoved > 0)
//把index索引之后的元素全部前移一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//把数组最后一个存在元素的位置赋值为空
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
remove(Object o)删除指定元素
public boolean remove(Object o) {
if (o == null) {
//传入为null
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
//完成数组元素的删除
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
//要移动元素个数
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
}