概述
文章的内容基于JDK1.8进行分析。
- ArrayList实现了List的全部接口功能,它封装了一个Object[]类型的数组,长度可以动态的增长。
- 如果在创建ArrayList时没有指定Object[]数组的长度,它默认创建一个长度为10的数组,当新添加的元素已经没有位置存放的时候,ArrayList就会自动进行扩容,扩容的长度为原来长度的1.5倍。
- ArrayList的线程是不安全的。
源码分析
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//可序列化版本号
private static final long serialVersionUID = 8683452581122892189L;
//默认的初始化数组大小为10
private static final int DEFAULT_CAPACITY = 10;
//实例化一个空对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//实例化一个空对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//存放List元素的对象数组,反序列化
transient Object[] elementData; // 非私有,以简化嵌套类访问
//List中存放元素的实际数量
private int size;
/**
* 指定数组长度的构造方法
*/
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);
}
}
/**
* 默认数组长度的无参构造方法
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 参数为集合的构造方法
*/
public ArrayList(Collection<? extends E> c) {
//将集合转换为数组
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// 如果数组不为空,如果不是Object[]类型的数组,转换为Object[]类型
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 如果数组为空,将elementData设为空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}
/**
* 改变数组的长度,使长度和List的size相等
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
/**
* 确定ArrayList的容量
* 判断当前elementData是否是EMPTY_ELEMENTDATA,若是设置长度为10
*/
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
//是否需要扩容
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
/**
* 当前位置和默认大小之间取最大值
*/
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 数组的最大容量,Integer的最大值-8
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 扩容操作
*/
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:
//生成一个长度为newCapacity数组,并将elementData数组中元素拷贝到新数组中,并将新数组的引用赋值给elementData
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
/**
* 返回数组中已经放入的元素个数,非数组长度
*/
public int size() {
return size;
}
/**
* List是否为空
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 判断是否包包含指定元素
*/
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* 查找指定的元素,存在返回下标,不存在放回 -1
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
/**
* 倒序查找元素,存在放回下标,不存在返回-1
*/
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -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);
}
}
/**
* 将集合转化为数组
*/
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
/**
* 转化为指定类型的数组元素,推荐使用此方法
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
// Positional Access Operations
/**
* 放回指定位置的数组元素
*/
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
/**
* 返回列表中指定位置的元素
*/
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
/**
* 设置指定位置的元素,并返回被替换的元素
*/
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
/**
* 添加元素
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* 将元素添加到指定位置上,从指定位置的元素开始所有元素向后移动,为新添加的元素提供位置
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* 删除指定位置的元素,其他元素做相依的移动,并将最后一个元素置空,
* 方便垃圾处理机制回收,防止内存泄露,并返回删除的元素值
*/
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;
}
/**
* 删除元素方法
*/
public boolean remove(Object o) {
if (o == 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
}
/**
* 清除列表
*/
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
/**
* 添加方法,添加的元素为集合
*/
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
/**
* 从指定位置开始添加集合元素
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
/**
* 范围删除方法
*/
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);
// clear to let GC do its work
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;
}
size = newSize;
}
/**
* 下标检测方法,如果不合法,抛出IndexOutOfBoundsException异常
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* A version of rangeCheck used by add and addAll.
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 溢出信息
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
/**
* 删除所有元素
* @see Collection#contains(Object)
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
省略后面代码...
}
扩容机制
扩容机制是发生在添加元素的时候,数组初始化之后容量是不变的,当新增元素时,先要进行扩容检测:
/**
* 添加元素
*/
public boolean add(E e) {
//检测扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//元素实际数量加一并添加元素到数组末尾
elementData[size++] = e;
return true;
}
这里看到是通过私有方法 ensureCapacityInternal 来进行数组的扩容操作:
//内部数组的默认容量
private static final int DEFAULT_CAPACITY = 10;
//空的内部数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//关键 -> minCapacity = seize+1,即表示执行完添加操作后,数组中的元素个数
private void ensureCapacityInternal(int minCapacity) {
//判断内部数组是否为空
if (elementData == EMPTY_ELEMENTDATA) {
//设置数组最小容量(>=10)
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
判断数组是否为空,为空则建默认的容量10赋值给minCapacity,判断是否要扩容,第一次添加,数组的size是10,之后添加元素时,进入ensureExplicitCapacity方法:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//添加后数组容量大于当前数组容量进行扩容
if (minCapacity - elementData.length > 0){
//扩容操作
grow(minCapacity);
}
}
这个方法中判断数组元素个数即size+1(形参minCapacity)是否超过数组长度,超过则需要进入grow方法进行扩容操作:
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
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);
}
//复制旧数组元素到新数组中去
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0){
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
扩容是将旧的容量扩大到1.5倍,然后将数组拷贝到新的数组完成扩容操作,最后将元素添加,并size+1