ArrayList底层的数据结构是数组,它是线程不安全的,ArrayList允许元素为null,实现RandomAccess接口,表明List提供了随机快速访问功能,可以以O(1)的时间复杂度根据下标访问元素,本文就以JDK1.8源码为例深入探讨ArrayList的结构实现和功能原理。
类结构图
public class ArrayList
类注释
(1) ArrayList是一个动态数组,容量可以动态的增加,允许存储null元素。
(2) size、isEmpty、get、set、iterator、listIterator操作以恒定的时间运行,add操作在恒定的平摊时间内运行[也就是说添加n个元素需要0(n)的时间]。
(3) 每个ArrayList都包含一个capacity。
(4) 在添加大量元素之前使用ensureCapacity操作,可以减少增量重新分配的数量。
(5) ArrayList它是线程不安全,通过Collections.synchronizedList实现线程安全。
类常量
//无参构造方法创建对象时,ArrayList的默认初始化长度
private static final int DEFAULT_CAPACITY = 10;
//空的对象数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//空的对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//保存ArrayList对象的数组缓冲区,真正存放元素的数组[ArrayList底层是数组的实现]
//transient修饰的属性不会被序列化
transient Object[] elementData; // non-private to simplify nested class access
//当前集合中实际元素的数量,与[elementData.length]是有区别
private int size;
构造函数
//无参构造方法
public ArrayList() {
//将空数组赋值给elementData
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//带初始容量的构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//新建一个长度为initialCapacity的Object数组.
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//直接将EMPTY_ELEMENTDATA赋值给elementData
this.elementData = EMPTY_ELEMENTDATA;
} else {
//容量小于0抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
//利用Collection集合来构建构造函数
public ArrayList(Collection extends E> c) {
//利用Collection.toArray()方法得到一个Object[]数组,赋值给elementData
elementData = c.toArray();
//原数组size不为0
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
//c.toArray可能出错,返回类型不是Object
if (elementData.getClass() != Object[].class)
//修改集合c中为Object类型
//利用Arrays.copyOf()来复制集合c中的元素到elementData数组中
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
//直接将EMPTY_ELEMENTDATA赋值给elementData
this.elementData = EMPTY_ELEMENTDATA;
}
}
//通过Arrays.copyOf()方法返回Object[]数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
@SuppressWarnings("unchecked")
public T[] toArray(T[] a) {
//a.length小于size
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
//返回一个新的数组
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//a.length等于size,返回a数组
System.arraycopy(elementData, 0, a, 0, size);
//a.length大于size
if (a.length > size)
//把a[size]清空
a[size] = null;
return a;
}
//copyOf()的重载函数
@SuppressWarnings("unchecked")
public static T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
//copyOf()的重载函数
public static T[] copyOf(U[] original, int newLength, Class extends T[]> newType) {
@SuppressWarnings("unchecked")
//根据class的类型来决定是new还是反射去构造一个数组
T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength);
//利用native函数,复制[original]元素至新的[copy]数组中 [常用函数]
System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));
return copy;
}
//System类中的native方法
//src 原数组 srcPos 原数组开始拷贝的位置
//dest 目标数组 destPos 目标数组开始拷贝的位置
//length 拷贝原数组的长度[开始位置 = srcPos]
public static native void arraycopy(Object src,int srcPos,Object dest,int destPos,int length);
常用函数 - add
public boolean add(E e) {
//判断add之后是否需要扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
//[赋值]在数组末尾追加一个元素并修改size
//等同于elementData[size] = e; size = size + 1;
elementData[size++] = e;
return true;
}
//调用ensureCapacityInternal(int minCapacity)
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//size默认值0添加一个元素时minCapacity=1,返回最小容量为10
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//判断数组是否等于默认空的构造函数
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//返回max(Capacity)
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//数组不为空直接返回
return minCapacity;
}
//调用ensureExplicitCapacity(int minCapacity)
private void ensureExplicitCapacity(int minCapacity) {
//如果确定要扩容,会修改modCount
modCount++;
// overflow-conscious code
//判断是否需要扩容
if (minCapacity - elementData.length > 0)
//执行扩容
grow(minCapacity);
}
//第一次扩容是0到10,扩容有可能超过0.5倍或达不到0.5倍。
private void grow(int minCapacity) {
// overflow-conscious code
//获取数组长度[原数组容量]
int oldCapacity = elementData.length;
//新的容量等于原有容量 + 0.5 * oldCapacity [右移一位等于除以2]
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新容量小于最小容量,按照最小容量进行扩容
//如果传入参数 > 1.5倍原容量,新容量 = 传入参数
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:
//调用Arrays.copyOf()方法扩容[拷贝],构建一个新的数组[new 或 反射]
elementData = Arrays.copyOf(elementData, newCapacity);
}
//add(int index, E element)
public void add(int index, E element) {
//判断是否越界[(index > size || index < 0)]
rangeCheckForAdd(index);
//判断add之后是否需要扩容
ensureCapacityInternal(size + 1); // Increments modCount!!
// //将index开始的数据向后移动一位[调用System.arraycopy],比较耗费资源
System.arraycopy(elementData, index, elementData, index + 1,size - index);
//空出来的index位置插入element元素
elementData[index] = element;
//数组中的元素 + 1
size++;
}
//判断是否出现下标是否越界
private void rangeCheckForAdd(int index) {
//index大于集合的大小或小于0提示越界
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//异常输出处理
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
//添加Collection集合元素
public boolean addAll(Collection extends E> c) {
//利用Collection.toArray()方法得到一个Object[]数组
Object[] a = c.toArray();
//获取数组长度
int numNew = a.length;
//判断是否需要扩容
ensureCapacityInternal(size + numNew); // Increments modCount
//复制数组
System.arraycopy(a, 0, elementData, size, numNew);
//数组中的元素 + numNew
size += numNew;
return numNew != 0;
}
public boolean addAll(int index, Collection extends E> c) {
//判断数组是否越界
rangeCheckForAdd(index);
//利用Collection.toArray()方法得到一个Object[]数组
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);
//数组中的元素 + numNew
size += numNew;
return numNew != 0;
}
常用函数 - remove
public E remove(int index) {
//判断是否越界
rangeCheck(index);
//修改modeCount,因为结构改变了
modCount++;
//读出index位置的元素
E oldValue = elementData(index);
//计算移动元素的数量
int numMoved = size - index - 1;
if (numMoved > 0)
//拷贝覆盖数组数据
System.arraycopy(elementData, index+1, elementData, index,numMoved);
//清空原尾部数据,不再强引用,方便GC回收[避免内存泄露]
elementData[--size] = null; // clear to let GC do its work
//返回待删除的元素
return oldValue;
}
//判断是否越界
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//获取指定位置元素
E elementData(int index) {
return (E) elementData[index];
}
//删除数组中第一次出现位置上的数据,删除成功返回true
public boolean remove(Object o) {
//判断对象是否为空
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
//根据index删除指定元素
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
//根据index删除指定元素
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
//修改modCount
modCount++;
//计算移动元素的数量
int numMoved = size - index - 1;
if (numMoved > 0)
//拷贝覆盖数组数据[index后面的元素向前移动一位]
System.arraycopy(elementData, index+1, elementData, index,numMoved);
//清空原尾部数据,不再强引用,方便GC回收
elementData[--size] = null; // clear to let GC do its work
}
protected void removeRange(int fromIndex, int toIndex) {
//修改modCount
modCount++;
//计算移动元素的数量
int numMoved = size - toIndex;
//把toIndex后面的元素拷贝到fromIndex后面
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;
}
//批量删除-底层调用batchRemove
public boolean removeAll(Collection> c) {
//判断集合是否为空,为空抛出NPE
Objects.requireNonNull(c);
//批量删除[complement = false]
return batchRemove(c, false);
}
//取交集-底层调用batchRemove
public boolean retainAll(Collection> c) {
Objects.requireNonNull(c);
//批量删除[complement = true]
return batchRemove(c, true);
}
//批量删除 complement = [false | true]
private boolean batchRemove(Collection> c, boolean complement) {
//初始化数组
final Object[] elementData = this.elementData;
//w是删除之后数组中剩余数量
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)//高效保存[删除和取交集通用方法]
//如果c.contains(elementData[r]) == complement,保留elementData[r]元素
if (c.contains(elementData[r]) == complement)
//数据赋值并保留,[complement有可能是true|false]
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
//正常情况下r == size,出现ClassCastException[类转换异常]下r != size
if (r != size) {
//把r位置之后的元素拷贝到w位置之后
System.arraycopy(elementData,r,elementData,w,size - r);
//数组元素数量增加
w += size - r;
}
if (w != size) {
//删除w位置之后的元素
// clear to let GC do its work
for (int i = w; i < size; i++)
//置空,方便GC回收
elementData[i] = null;
//删除size - w次
modCount += size - w;
//数组中剩余数量
size = w;
//删除成功返回true
modified = true;
}
}
return modified;
}
常用函数 - set
public E set(int index, E element) {
//检查是否越界
rangeCheck(index);
//获取元素
E oldValue = elementData(index);
//覆盖元素
elementData[index] = element;
//返回oldValue
return oldValue;
}
常用函数 - get
public E get(int index) {
//检查是否越界
rangeCheck(index);
//获取指定下标元素
return elementData(index);
}
//获取指定下标元素
E elementData(int index) {
//实际存储数据的数组elementData
return (E) elementData[index];
}
常用函数 - clear
public void clear() {
//修改modCount
modCount++;
// clear to let GC do its work
//清空elementData数组,方便GC回收
for (int i = 0; i < size; i++)
elementData[i] = null;
//修改size = 0
size = 0;
}
常用函数 - size
public int size() {
//返回当前集合中实际元素的数量
return size;
}
//判断集合是否为空
public boolean isEmpty() {
return size == 0;
}
常用函数 - contains
public boolean contains(Object o) {
//判断集合中是否包含该元素
return indexOf(o) >= 0;
}
//对象循环查找获取首次出现位置
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;
}
//对象不存在,返回 -1
return -1;
}
//对象循环查找获取最后一次出现位置
public int lastIndexOf(Object o) {
//对象为空,遍历集合,空用"=="判断
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
//返回元素最后一次出现位置
return i;
} else {
//对象不为空,遍历集合,用"equals()"判断
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
//返回元素最后一次出现位置
return i;
}
//对象不存在,返回 -1
return -1;
}
常用函数 - trimToSize
//将底层数组的容量调整为当前实际元素的大小,解决空间
public void trimToSize() {
modCount++;
//实际元素的大小 小于 当前数组长度
if (size < elementData.length) {
//进行缩容
elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);
}
}
常用函数 - clone
public Object clone() {
try {
//数组克隆
ArrayList> v = (ArrayList>) super.clone();
//拷贝并赋值给v
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);
}
}
常用函数 - Iterator
public Iterator iterator() {
return new Itr();
}
private class Itr implements Iterator {
//默认是0
int cursor; // index of next element to return
//上一次返回的元素位置
int lastRet = -1; // index of last element returned; -1 if no such
//用于判断集合是否修改过结构的标志
int expectedModCount = modCount;
//空的构造函数
Itr() {}
//游标是否移动至数组尾部
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
//判断是否修改过
checkForComodification();
int i = cursor;
//判断是否越界
if (i >= size)
throw new NoSuchElementException();
//获取elementData元素
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
//游标 + 1
cursor = i + 1;
//返回元素 ,并设置上一次返回的元素的下标
return (E) elementData[lastRet = i];
}
public void remove() {
//是否执行或next()
if (lastRet < 0)
throw new IllegalStateException();
//判断是否修改过
checkForComodification();
try {
//删除元素remove方法内会修改modCount
ArrayList.this.remove(lastRet);
//要删除的游标
cursor = lastRet;
//不能重复删除 所以修改删除的标志位
lastRet = -1;
//更新判断集合是否修改的标志
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
//判断是否修改过了List的结构,如果有修改,抛出异常[并发处理]
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
常用函数 - 序列化反序列化
//序列化
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
// Write out element count, and any hidden stuff
//fail-fast机制,用于后续判断是否有并发处理
int expectedModCount = modCount;
//序列化没有标记为static、transient的字段
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
//按照size的大小进行序列化[没有直接序列化elementData数组]
for (int i=0; i 0) {
// be like clone(), allocate array based upon size not capacity
int capacity = calculateCapacity(elementData, size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
//数组扩容
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
//按照size大小反序列化元素并填充到数组中
for (int i=0; i
扩展问题
ArrayList和LinkedList的区别
(1) ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
(2) 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
(3) 对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
ArrayList和Vector的区别
(1) Vector和ArrayList几乎是完全相同的[底层都是数组],唯一的区别在于Vector是同步类(synchronized),因此开销就比ArrayList要大、访问要慢。
(2 ) Vector每次扩容是其大小的2倍空间,而ArrayList扩容是1.5倍。
(3) Vector还有一个子类Stack。