arrayList源码解析

public class ArrayList<E> extends AbstractList<E>  

implements List<E>, RandomAccess, Cloneable, java.io.Serializable 

 

0.ArrayList元素定义:

//存储数组元素的缓冲区;也就是真实的ArrayList的盒子大小

transient Object[] elementData;

//默认空数组元素

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//默认初始化容量

private static final int DEFAULT_CAPACITY = 10;

//数组的大小,也就是真实ArrayList里面存的东西多少

private int size;

//记录被修改的次数

protected transient int modCount = 0;

//数组的最大值

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8

 

1.ArrayList的构造函数:

无参构造函数:

public ArrayList() {

//初始化一个空的数组,在JDK1.8以后默认数组长度10,不在构造函数时创建,实在add操作时初始化

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

定义长度的构造函数:

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(Collection<? extends E> c) {

//将集合定义为数组复制给缓冲区(arrayList底层)

elementData = c.toArray();

//集合不为空

if ((size = elementData.length) != 0) {

//不为空,如果类型不一样,调用复制方法;将集合复制给新的arrayList

if (elementData.getClass() != Object[].class)

elementData = Arrays.copyOf(elementData, size, Object[].class);

} else {

//集合为空;定义一个空数组

this.elementData = EMPTY_ELEMENTDATA;

}

}

2.添加元素add:

添加元素:

public boolean add(E e) {

//扩充长度,在原来的大小上面加1 

ensureCapacityInternal(size + 1); // Increments modCount!!

//添加元素

elementData[size++] = e;

return true;

}

或者

public void add(int index, E element) {

//判断index是否越界

rangeCheckForAdd(index);

ensureCapacityInternal(size + 1); // Increments modCount!!

System.arraycopy(elementData, index, elementData, index + 1, size - index);

elementData[index] = element;

size++;

}

判断是否越界:

private void rangeCheckForAdd(int index) {

//小于0或者大于size都数组越界

if (index > size || index < 0)

throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

}

计算容量:

//minCapacit原本长度+1---》因为新添加一个元素,肯定要默认长度+1

private void ensureCapacityInternal(int minCapacity) {

//如果这个数组等于空,返回最大的容量,否则,还是原来的容量+1 

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

}

ensureExplicitCapacity(minCapacity);

}

确认扩展容量

private void ensureExplicitCapacity(int minCapacity) {

//修改次数+1

modCount++;

// 如果容量不够,调用增加容量方法

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

扩展方法

private void grow(int minCapacity) {

// 获取原来数组容量的长度,老的数组长度

int oldCapacity = elementData.length;

//新增加的容量长度为原来容量的1.5倍 

int newCapacity = oldCapacity + (oldCapacity >> 1);

//新的容量小于需要的容量;那么新的容量=需要的容量

if (newCapacity - minCapacity < 0)//只有之前该list为空的情况,才创建list长度为10

newCapacity = minCapacity;

//新创建的容量(1.5)超过数组的最大值。按照最大的长度创建list

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);//为数组的最大值

// 调用复制方法,在原来元素上增加容量,这就是传说中的可变集合。用新长度复制原数组

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 static <T,U> T[] copyOf(U[] original, int newLength,

Class<? extends T[]> newType) {

@SuppressWarnings("unchecked")

获得者数组对象(创建一个长度为1.5oldLength的新数组)

T[] copy = ((Object)newType == (Object)Object[].class)

? (T[]) new Object[newLength]

: (T[]) Array.newInstance(newType.getComponentType(), newLength);

 

调用系统的方法增加数组容量;(将老的数组复制到新数组中。)

System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));

return copy;

}

3.当ArrayList中有空闲的空间时,缩减ArrayList的容量;应用程序可以使用这个方法最小化ArrayList实例

public void trimToSize() {

modCount++;//记录修改次数

//判断真实数组的长度是否小于扩容缓存的长度

if (size < elementData.length) {

//如果数组的大小为0,则给该ArrayList定义为空数组,否则按照真实的数组长度定义ArrayList容量长度

elementData = (size == 0)? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);

}

}

4.确定容量

public void ensureCapacity(int minCapacity) {

//最小扩容长度;如果该ArrayList不为空;可以不进行扩容0;如果为空就要进行默认长度10

int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY;

 

if (minCapacity > minExpand) {

ensureExplicitCapacity(minCapacity);

}

}

5.ArrayList的克隆;因为实现了Cloneable接口,所以支持克隆

//可以一个完全一样的ArrayList

public Object clone() {

try {

ArrayList<?> v = (ArrayList<?>) super.clone();

v.elementData = Arrays.copyOf(elementData, size);

v.modCount = 0;

return v;

} catch (CloneNotSupportedException e) {

throw new InternalError(e);

}

}

6.删除操作

/**

* 移除此列表中指定位置上的元素

* @param index 需被移除的元素的索引

* @return the element 被移除的元素值

* @throws IndexOutOfBoundsException {@inheritDoc}

*/

public E remove(int index) {

rangeCheck(index); //判断index是否 <= size

 

modCount++;

E oldValue = elementData(index);

//将数组elementData中index位置之后的所有元素向前移一位

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[--size] = null; //将原数组最后一个位置置为null,由GC清理

 

return oldValue;

}

 

//移除ArrayList中首次出现的指定元素(如果存在),ArrayList中允许存放重复的元素

public boolean remove(Object o) {

// 由于ArrayList中允许存放null,因此下面通过两种情况来分别处理。

if (o == null) {

for (int index = 0; index < size; index++)

if (elementData[index] == null) {

fastRemove(index); //私有的移除方法,跳过index参数的边界检查以及不返回任何值

return true;

}

} else {

for (int index = 0; index < size; index++)

if (o.equals(elementData[index])) {

fastRemove(index);

return true;

}

}

return false;

}

 

//私有的删除指定位置元素的方法,跳过index参数的边界检查以及不返回任何值

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

}

 

//清空ArrayList,将全部的元素设为null

public void clear() {

modCount++;

 

// clear to let GC do its work

for (int i = 0; i < size; i++)

elementData[i] = null;

 

size = 0;

}

 

//删除ArrayList中从fromIndex(包含)到toIndex(不包含)之间所有的元素,共移除了toIndex-fromIndex个元素

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;

}

 

//删除ArrayList中包含在指定容器c中的所有元素

public boolean removeAll(Collection<?> c) {

Objects.requireNonNull(c); //检查指定的对象c是否为空

return batchRemove(c, false);

}

 

//移除ArrayList中不包含在指定容器c中的所有元素,与removeAll(Collection<?> c)正好相反

public boolean retainAll(Collection<?> c) {

Objects.requireNonNull(c);

return batchRemove(c, true);

}

 

private boolean batchRemove(Collection<?> c, boolean complement) {

final Object[] elementData = this.elementData;

int r = 0, w = 0; //读写双指针

boolean modified = false;

try {

for (; r < size; r++)

if (c.contains(elementData[r]) == complement) //判断指定容器c中是否含有elementData[r]元素

elementData[w++] = elementData[r];

} finally {

// Preserve behavioral compatibility with AbstractCollection,

// even if c.contains() throws.

if (r != size) {

System.arraycopy(elementData, r,

elementData, w,

size - r);

w += size - r;

}

if (w != size) {

// clear to let GC do its work

for (int i = w; i < size; i++)

elementData[i] = null;

modCount += size - w;

size = w;

modified = true;

}

}

return modified;

}

6.修改操作

 

//将指定索引上的值替换为新值,并返回旧值

public E set(int index, E element) {

//检查是否index越界

rangeCheck(index);

 

E oldValue = elementData(index);

elementData[index] = element;

return oldValue;

}

7.查找元素

//判断ArrayList中是否包含Object(o)

public boolean contains(Object o) {

return indexOf(o) >= 0;

}

 

//正向查找,返回ArrayList中元素Object o第一次出现的位置,如果元素不存在,则返回-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;

}

 

//逆向查找,返回ArrayList中元素Object o最后一次出现的位置,如果元素不存在,则返回-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;

}

 

@SuppressWarnings("unchecked")

E elementData(int index) {

return (E) elementData[index];

}

 

//返回指定索引处的值

public E get(int index) {

rangeCheck(index);

 

return elementData(index); //实质上return (E) elementData[index]

}

8.序列化和反序列化

//序列化:将ArrayList的“大小,所有的元素值”都写入到输出流中

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException{

// Write out element count, and any hidden stuff

int expectedModCount = modCount;

s.defaultWriteObject();

 

// Write out size as capacity for behavioural compatibility with clone()

s.writeInt(size);

 

// Write out all elements in the proper order.

for (int i=0; i<size; i++) {

s.writeObject(elementData[i]);

}

 

if (modCount != expectedModCount) {

throw new ConcurrentModificationException();

}

}

 

//反序列化:先将ArrayList的“大小”读出,然后将“所有的元素值”读出

private void readObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {

elementData = EMPTY_ELEMENTDATA;

 

// Read in size, and any hidden stuff

s.defaultReadObject();

 

// Read in capacity

s.readInt(); // ignored

 

if (size > 0) {

// be like clone(), allocate array based upon size not capacity

ensureCapacityInternal(size);

 

Object[] a = elementData;

// Read in all elements in the proper order.

for (int i=0; i<size; i++) {

a[i] = s.readObject();

}

}

}

9.其他方法:

 

//返回ArrayList的大小(元素个数)

public int size() {

return size;

}

 

//判断ArrayList是否为空

public boolean isEmpty() {

return size == 0;

}

 

//返回此 ArrayList实例的浅拷贝

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);

}

}

//返回一个包含ArrayList中所有元素的数组

public Object[] toArray() {

return Arrays.copyOf(elementData, size);

}

 

//如果给定的参数数组长度足够,则将ArrayList中所有元素按序存放于参数数组中,并返回

//如果给定的参数数组长度小于ArrayList的长度,则返回一个新分配的、长度等于ArrayList长度的、包含ArrayList中所有元素的新数组

@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;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章