Java集合—ArrayList的源码解读
ArrayList 概述
ArrayList的是基于数据来实现的,它是一个动态数组,它会自动扩容。ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用 Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类,或者Vector。
1 定义
ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。
ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializabl
{
}
2 属性
serialVersionUID 提供序列化的UID,保证不同平台反序列化可以成功。
DEFAULT_CAPACITY 定义ArrayList默认的容器大小。
EMPTY_ELEMENTDATA,DEFAULTCAPACITY_EMPTY_ELEMENTDATA 数组在初始化的时候使用,主要是为了初始化不会另外的创建对象,节约内存使用。
elementData数组用来存储ArrayList元素。需要解释的是transient 关键字:java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。
size 是指数组元素
private static final long serialVersionUID = 8683452581122892189L;
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = new Object[0];
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
transient Object[] elementData;
private int size;
private static final int MAX_ARRAY_SIZE = 2147483639;
3 构造函数
ArrayList定义了三个构造函数。第一个构造函数是可以指定数组元素大小的,第二个是不带参数的构造函数,它也是我们最常用的一种初始化方式,不申请内存,默认数组大小为0。第三个构造函数使用collection集合来初始化,使之包含collection元素。
public ArrayList(int paramInt)
{
if (paramInt > 0) { // 值得我们学习的是对函数传入参数的判定,保持代码的健壮性
this.elementData = new Object[paramInt];
} else if (paramInt == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: " + paramInt);
}
}
public ArrayList()
{
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(Collection<? extends E> paramCollection)
{
this.elementData = paramCollection.toArray();
if ((this.size = this.elementData.length) != 0)
{
if (this.elementData.getClass() != Object[].class) {
this.elementData = Arrays.copyOf(this.elementData, this.size, Object[].class);
}
}
else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
// 思考 使用new ArrayList() 和 new ArrayList(0)来初始化的区别 ???
解决这个问题则需要明白ArrayList是如何动态扩容的
//ArrayList使用此方法确定数组有足够的大小存储元素
private void ensureCapacityInternal(int paramInt)
{
if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
paramInt = Math.max(10, paramInt); //大部分情况下this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA时paramInt会小于10,因此当使用new ArrayList()初始化时第一次申请的数组大小为10
}
ensureExplicitCapacity(paramInt);
}
private void ensureExplicitCapacity(int paramInt)
{
this.modCount += 1;
if (paramInt - this.elementData.length > 0) {//数组的长度不够时,调用grow申请内存
grow(paramInt);
}
}
private void grow(int paramInt)
{
int i = this.elementData.length;//elementData数组的长度
int j = i + (i >> 1);// 即j = i +i/2 增加原来1/2的长度
if (j - paramInt < 0) { //如果j< paramInt 则将j赋值围paramInt
j = paramInt;
}
if (j - 2147483639 > 0) { // 判断是否超过最大长度,超过则申请Integer.MAX_VALUE的元素内存
j = hugeCapacity(paramInt);
}
this.elementData = Arrays.copyOf(this.elementData, j);//copyOf方法复制指定的数组,截取或用null填充(如有必要),以使副本具有指定的长度
}
private static int hugeCapacity(int paramInt)
{
if (paramInt < 0) {
throw new OutOfMemoryError();
}
return paramInt > 2147483639 ? Integer.MAX_VALUE : 2147483639;
}
回到上面的问题,使用new ArrayList() 和 new ArrayList(0)来初始化的区别?
使用new ArrayList() 第一次调用ensureCapacityInternal时,this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA成立,paramInt会被赋予10,,grow函数中由于elementData.length =0 所以i=0,j=0, j-paramInt<0成立,j被赋值为10,Arrays.copyOf(this.elementData, j)第一次申请的数组大小为10.如果使用new ArrayList(0)当第一次调用ensureCapacityInternal函数时,通常传入的参数为1. j最终等于1,只会申请数组大小为1的内存。
**常用方法**
public int size()
{
return this.size;//返回size表示数组中包含元素的数量
}
public boolean isEmpty()
{
return this.size == 0;// size==0 意味elementData中没有存储任何元素
}
public boolean contains(Object paramObject)
{
return indexOf(paramObject) >= 0;//indexof返回-1表示数组中不包含该对象
}
// indexof返回paramObject对象的索引位置。分两种情况,
// paramObject为null和不为null的情况。
public int indexOf(Object paramObject)
{
int i;
//如果paramObject为null,则判断数组中是否包含null元素
if (paramObject == null) {
for (i = 0; i < this.size; i++) {
if (this.elementData[i] == null) {
return i;
}
}
} else {
//不为空则判断数组中是否存在paramObject对象
for (i = 0; i < this.size; i++) {
if (paramObject.equals(this.elementData[i])) {
return i;
}
}
}
return -1;
}
//反向寻找是否包含paramObject对象
public int lastIndexOf(Object paramObject)
{
int i;
if (paramObject == null) {
for (i = this.size - 1; i >= 0; i--) {
if (this.elementData[i] == null) {
return i;
}
}
} else {
for (i = this.size - 1; i >= 0; i--) {
if (paramObject.equals(this.elementData[i])) {
return i;
}
}
}
return -1;
}
public Object clone()
{
try
{
ArrayList localArrayList = (ArrayList)super.clone();
localArrayList.elementData = Arrays.copyOf(this.elementData, this.size);
localArrayList.modCount = 0;
return localArrayList;
}
catch (CloneNotSupportedException localCloneNotSupportedException)
{
throw new InternalError(localCloneNotSupportedException);
}
}
// 将ArrayList转换为数组
public Object[] toArray()
{
return Arrays.copyOf(this.elementData, this.size);
}
public <T> T[] toArray(T[] paramArrayOfT)
{
if (paramArrayOfT.length < this.size) {
return (Object[])Arrays.copyOf(this.elementData, this.size, paramArrayOfT.getClass());
}
System.arraycopy(this.elementData, 0, paramArrayOfT, 0, this.size);
if (paramArrayOfT.length > this.size) {
paramArrayOfT[this.size] = null;
}
return paramArrayOfT;
}
//返回数组中位置为paramInt的元素
E elementData(int paramInt)
{
return (E)this.elementData[paramInt];
}
// 获得第paramInt位置的元素
public E get(int paramInt)
{
rangeCheck(paramInt);//保证paramInt小于size
return (E)elementData(paramInt);
}
//设置位置paramInt的元素为paramE
public E set(int paramInt, E paramE)
{
//保证paramInt小于size
rangeCheck(paramInt);
Object localObject = elementData(paramInt);
this.elementData[paramInt] = paramE;
return (E)localObject;
}
//往elementData数组中增加元素paramE
public boolean add(E paramE)
{ //确保elementData数组足够的空间存放paramE
ensureCapacityInternal(this.size + 1);
this.elementData[(this.size++)] = paramE;
return true;
}
//往位置paramInt增加元素paramE
public void add(int paramInt, E paramE)
{
rangeCheckForAdd(paramInt);
ensureCapacityInternal(this.size + 1);
System.arraycopy(this.elementData, paramInt, this.elementData, paramInt + 1, this.size - paramInt);
this.elementData[paramInt] = paramE;
this.size += 1;
}
//移除位置paramInt的元素
public E remove(int paramInt)
{
rangeCheck(paramInt);
this.modCount += 1;
Object localObject = elementData(paramInt);
int i = this.size - paramInt - 1;
if (i > 0) {
System.arraycopy(this.elementData, paramInt + 1, this.elementData, paramInt, i);
}
this.elementData[(--this.size)] = null;
return (E)localObject;
}
//移除paramObject对象
public boolean remove(Object paramObject)
{
int i;
if (paramObject == null) {
for (i = 0; i < this.size; i++) {
if (this.elementData[i] == null)
{
fastRemove(i);
return true;
}
}
} else {
for (i = 0; i < this.size; i++) {
if (paramObject.equals(this.elementData[i]))
{
fastRemove(i);
return true;
}
}
}
return false;
}
//快速移除paramInt的元素
private void fastRemove(int paramInt)
{
this.modCount += 1;
int i = this.size - paramInt - 1;
if (i > 0) {
System.arraycopy(this.elementData, paramInt + 1, this.elementData, paramInt, i);
}
this.elementData[(--this.size)] = null;
}
//清除数组中的元素
public void clear()
{
this.modCount += 1;
for (int i = 0; i < this.size; i++) {
this.elementData[i] = null;
}
this.size = 0;
}
//讲集合paramCollection中的元素添加到数组中
public boolean addAll(Collection<? extends E> paramCollection)
{
Object[] arrayOfObject = paramCollection.toArray();
int i = arrayOfObject.length;
ensureCapacityInternal(this.size + i);
System.arraycopy(arrayOfObject, 0, this.elementData, this.size, i);
this.size += i;
return i != 0;
}
//讲paramCollection中的元素添加到位置paramInt后
public boolean addAll(int paramInt, Collection<? extends E> paramCollection)
{
rangeCheckForAdd(paramInt);
Object[] arrayOfObject = paramCollection.toArray();
int i = arrayOfObject.length;
ensureCapacityInternal(this.size + i);
int j = this.size - paramInt;
if (j > 0) {
System.arraycopy(this.elementData, paramInt, this.elementData, paramInt + i, j);
}
System.arraycopy(arrayOfObject, 0, this.elementData, paramInt, i);
this.size += i;
return i != 0;
}
//移除paramInt1到paramInt2的元素
protected void removeRange(int paramInt1, int paramInt2)
{
this.modCount += 1;
int i = this.size - paramInt2;
System.arraycopy(this.elementData, paramInt2, this.elementData, paramInt1, i);
int j = this.size - (paramInt2 - paramInt1);
for (int k = j; k < this.size; k++) {
this.elementData[k] = null;
}
this.size = j;
}
//检查paramInt是否大于数组元素的数量
private void rangeCheck(int paramInt)
{
if (paramInt >= this.size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt));
}
}
//判断paramInt的范围是否在(0,size)间
private void rangeCheckForAdd(int paramInt)
{
if ((paramInt > this.size) || (paramInt < 0)) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt));
}
}
private String outOfBoundsMsg(int paramInt)
{
return "Index: " + paramInt + ", Size: " + this.size;
}
//从列表中移除指定 collection 中包含的其所有元素
public boolean removeAll(Collection<?> paramCollection)
{
Objects.requireNonNull(paramCollection);
return batchRemove(paramCollection, false);
}
//取得paramCollection和ArraList**重点内容**的交集
public boolean retainAll(Collection<?> paramCollection)
{
Objects.requireNonNull(paramCollection);
return batchRemove(paramCollection, true);
}