ArrayList方法源码
三種構(gòu)造函數(shù)
不帶參數(shù)的構(gòu)造函數(shù)
public ArrayList() {// 如果沒有傳入初始容量,則使用空數(shù)組DEFAULTCAPACITY_EMPTY_ELEMENTDATA// 使用這個數(shù)組是在添加第一個元素的時候會擴容到默認大小10this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }帶初始容量的構(gòu)造函數(shù)
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {// 如果傳入的初始容量大于0,就新建一個數(shù)組存儲元素this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {// 如果傳入的初始容量等于0,使用空數(shù)組EMPTY_ELEMENTDATAthis.elementData = EMPTY_ELEMENTDATA;} else {// 如果傳入的初始容量小于0,拋出異常throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);} }帶集合的構(gòu)造函數(shù)
/** * 把傳入集合的元素初始化到ArrayList中 */ public ArrayList(Collection<? extends E> c) {// 集合轉(zhuǎn)數(shù)組elementData = c.toArray();if ((size = elementData.length) != 0) {// 檢查c.toArray()返回的是不是Object[]類型,如果不是,重新拷貝成Object[].class類型if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// 如果c的空集合,則初始化為空數(shù)組EMPTY_ELEMENTDATAthis.elementData = EMPTY_ELEMENTDATA;} }add(E e) 方法
public boolean add(E e) {// 檢查是否需要擴容ensureCapacityInternal(size + 1);// 把元素插入到最后一位elementData[size++] = e;return true; }private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }private static int calculateCapacity(Object[] elementData, int minCapacity) {// 如果是空數(shù)組DEFAULTCAPACITY_EMPTY_ELEMENTDATA,就初始化為默認大小10if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity; }private void ensureExplicitCapacity(int minCapacity) {modCount++;if (minCapacity - elementData.length > 0)// 擴容grow(minCapacity); }private void grow(int minCapacity) {int oldCapacity = elementData.length;// 新容量為舊容量的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);// 如果新容量發(fā)現(xiàn)比需要的容量還小,則以需要的容量為準if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 如果新容量已經(jīng)超過最大容量了,則使用最大容量if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 以新容量拷貝出來一個新數(shù)組elementData = Arrays.copyOf(elementData, newCapacity); }添加一個元素的過程頗為復(fù)雜,那么大致來說就是,會有個檢查是否擴容的方法。?
首先判斷elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,直接返回最小容量值 10 .
如果不是的話 那么就返回minCapacity。
minCapacity可以這么理解 要求最小的容量。
接下來又有一個判斷?if (minCapacity - elementData.length > 0)? 對這句話的理解為要求最小的容量比存儲數(shù)據(jù)的數(shù)組長度大的話,那么說明需要擴容了,就得執(zhí)行g(shù)row()方法了。
add(int index, E element)方法
public void add(int index, E element) {// 檢查是否越界rangeCheckForAdd(index);// 檢查是否需要擴容ensureCapacityInternal(size + 1);// 將inex及其之后的元素往后挪一位,則index位置處就空出來了System.arraycopy(elementData, index, elementData, index + 1,size - index);// 將元素插入到index的位置elementData[index] = element;// 大小增1size++; }private void rangeCheckForAdd(int index) {if (index > size || index < 0)throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }addAll 方法
/** * 將集合c中所有元素添加到當前ArrayList中 */ public boolean addAll(Collection<? extends E> c) {// 將集合c轉(zhuǎn)為數(shù)組Object[] a = c.toArray();int numNew = a.length;// 檢查是否需要擴容ensureCapacityInternal(size + numNew);// 將c中元素全部拷貝到數(shù)組的最后System.arraycopy(a, 0, elementData, size, numNew);// 大小增加c的大小size += numNew;// 如果c不為空就返回true,否則返回falsereturn numNew != 0; }?get(int index)方法
public E get(int index) {// 檢查是否越界rangeCheck(index);// 返回數(shù)組index位置的元素return elementData(index); }private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }E elementData(int index) {return (E) elementData[index]; }remove(int index)方法?
public E remove(int index) {// 檢查是否越界rangeCheck(index);modCount++;// 獲取index位置的元素E oldValue = elementData(index);// 如果index不是最后一位,則將index之后的元素往前挪一位int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index, numMoved);// 將最后一個元素刪除,幫助GCelementData[--size] = null; // clear to let GC do its work// 返回舊值return oldValue; }numMoved代表著需要前移多少個元素,如果等于0的話,那么此時的index=size-1? ?就是要刪除最后一個元素,所以直接將最后一個元素設(shè)為null即可。
remove(Object o)方法?
public boolean remove(Object o) {if (o == null) {// 遍歷整個數(shù)組,找到元素第一次出現(xiàn)的位置,并將其快速刪除for (int index = 0; index < size; index++)// 如果要刪除的元素為null,則以null進行比較,使用==if (elementData[index] == null) {fastRemove(index);return true;}} else {// 遍歷整個數(shù)組,找到元素第一次出現(xiàn)的位置,并將其快速刪除for (int index = 0; index < size; index++)// 如果要刪除的元素不為null,則進行比較,使用equals()方法if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false; }private void fastRemove(int index) {// 少了一個越界的檢查modCount++;// 如果index不是最后一位,則將index之后的元素往前挪一位int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index, numMoved);// 將最后一個元素刪除,幫助GCelementData[--size] = null; // clear to let GC do its work }總結(jié)
(1)ArrayList內(nèi)部使用數(shù)組存儲元素,當數(shù)組長度不夠時進行擴容,每次加一半的空間,ArrayList不會進行縮容;
(2)ArrayList支持隨機訪問,通過索引訪問元素極快,時間復(fù)雜度為O(1);
(3)ArrayList添加元素到尾部極快,平均時間復(fù)雜度為O(1);
(4)ArrayList添加元素到中間比較慢,因為要搬移元素,平均時間復(fù)雜度為O(n);
(5)ArrayList從尾部刪除元素極快,時間復(fù)雜度為O(1);
(6)ArrayList從中間刪除元素比較慢,因為要搬移元素,平均時間復(fù)雜度為O(n);
(7)ArrayList支持求并集,調(diào)用addAll(Collection<? extends E> c)方法即可;
(8)ArrayList支持求交集,調(diào)用retainAll(Collection<? extends E> c)方法即可;
(7)ArrayList支持求單向差集,調(diào)用removeAll(Collection<? extends E> c)方法即可;
?
總結(jié)
以上是生活随笔為你收集整理的ArrayList方法源码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: InnoDB和MyISAM有哪些不同
- 下一篇: LinkedList方法源码