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