?
ArrayList
基于數組實現,無容量的限制。
在執行插入元素時可能要擴容,在刪除元素時并不會減小數組的容量,在查找元素時要遍歷數組,對于非null的元素采取equals的方式尋找。
是非線程安全的。
注意點:
(1)ArrayList隨機存取元素時間復雜度O(1),插入刪除操作需大量移動元素,效率較低
(2)為了節約內存,當新建容器為空時,會共享
Object[] EMPTY_ELEMENTDATA = {}和
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}空數組
(3)容器底層采用數組存儲,每次擴容為1.5倍
(4)ArrayList的實現中大量地調用了Arrays.copyof()和System.arraycopy()方法,其實Arrays.copyof()內部也是調用System.arraycopy()。System.arraycopy()為Native方法
(5)兩個ToArray方法
Object[] toArray()方法。該方法有可能會拋出java.lang.ClassCastException異常
<T> T[] toArray(T[] a)方法。該方法可以直接將ArrayList轉換得到的Array進行整體向下轉型
(6)ArrayList可以存儲null值
(7)ArrayList每次修改(增加、刪除)容器時,都是修改自身的modCount;在生成迭代器時,迭代器會保存該modCount值,迭代器每次獲取元素時,會比較自身的modCount與ArrayList的modCount是否相等,來判斷容器是否已經被修改,如果被修改了則拋出異常(fast-fail機制)。
?
源碼解析
package java.util;import sun.misc.SharedSecrets;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {private static final long serialVersionUID = 8683452581122892189L;/*** 默認容量*/private static final int DEFAULT_CAPACITY = 10;/*** 對象數組*/private static final Object[] EMPTY_ELEMENTDATA = {};/*** 默認的空數組,無參構造函數創建的數組*/private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};/*** 存放數據的數組的緩存變量*/transient Object[] elementData;/*** 元素數量* */private int size;/*** 帶有容量的構造方法* * @param 數組的初始容量* @throws IllegalArgumentException 參數為負*/public ArrayList(int initialCapacity) {// 參數>0if (initialCapacity > 0) {// new一個object數組賦給elementDatathis.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {// 參數=0// 將空數組賦給elementDatathis.elementData = EMPTY_ELEMENTDATA;} else {//參數<0,拋出IllegalArgumentException異常throw new IllegalArgumentException("Illegal Capacity: " +initialCapacity);}}/*** 不帶參數構造方法*/public ArrayList() {// 將空數組賦給elementDatathis.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** 帶參數Collection的構造方法* * @param c* 其元素將被放入此列表中的集合* @throws NullPointerException* 集合為空*/public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray可能(錯誤地)不返回對象[](JAVA BUG編號6260652)if (elementData.getClass() != Object[].class)// Array.copyOf()主要用來將原數組拷貝到一個新的數組,適用于數組擴容。elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// 空數組this.elementData = EMPTY_ELEMENTDATA;}}/*** 因為容量基本會大于實際元素的數量。內存緊張時,可以調用該方法調整容量為元素實際數量。* 如果確定不會有元素添加進來時也可以調用該方法來節約空間*/public void trimToSize() {modCount++;// 如果size小于lengthif (size < elementData.length) {// 將elementData設置大小為sizeelementData = (size == 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size);}}/*** 使用指定參數設置數組容量* * @param minCapacity* 所需的最小容量*/public void ensureCapacity(int minCapacity) {// 如果數組為空,容量預取0,否則去默認值(10)int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if not default element table? 0// larger than default for default empty table. It's already// supposed to be at default size.: DEFAULT_CAPACITY;// 若參數大于預設的容量,再使用該參數進一步設置數組容量if (minCapacity > minExpand) {ensureExplicitCapacity(minCapacity);}}private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}/*** 得到最小擴容量* * @param minCapacity*/private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}/*** 判斷是否需要擴容* * @param minCapacity*/private void ensureExplicitCapacity(int minCapacity) {modCount++;// 最小需要空間比elementData的內存空間大if (minCapacity - elementData.length > 0)grow(minCapacity);}/*** 數組的最大容量,可能會導致內存溢出*/private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;/*** 擴容* * @param minCapacity* 所需的最小容量*/private void grow(int minCapacity) {// ArrayList中elementData的內存空間長度int oldCapacity = elementData.length;// 擴容原來的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);// 判斷新數組的容量夠不夠// 不夠就將數組長度設置為需要的長度if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 預設值>默認的最大值,檢查溢出if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 放到新數組中elementData = Arrays.copyOf(elementData, newCapacity);}/*** 檢查是否溢出,若沒有溢出,返回最大整數值或默認最大值* * @param minCapacity* @return*/private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // 溢出throw new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}/*** 返回ArrayList的大小* * @return ArrayList中的元素數量*/public int size() {return size;}/*** 返回是否為空* * @return true 如果ArrayList中無元素*/public boolean isEmpty() {return size == 0;}/*** 是否包含一個數 返回bool* * @param o* 被檢查元素* @return true 如果ArrayList中包含o元素*/public boolean contains(Object o) {return indexOf(o) >= 0;}/*** 返回一個值首次出現的位置,不存在就返回-1。時間復雜度O(N)* * 返回第一個null* @param o* @return*/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;}/*** 返回一個值最后一次出現的位置,不存在就返回-1。時間復雜度O(N)* 返回最后一個null* @param o* @return*/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;}/*** 返回副本,元素本身沒有被復制,復制過程中數組發生改變會拋出異常* * @return v ArrayList副本*/public Object clone() {try {// 調用Object類的clone方法得到ArrayList副本ArrayList<?> v = (ArrayList<?>) super.clone();// 調用copyOf,將ArrayList的elementData數組賦給副本的elementData數組v.elementData = Arrays.copyOf(elementData, size);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneablethrow new InternalError(e);}}/*** 轉換為Object數組* * @return 一個數組包含所有列表中的元素*/public Object[] toArray() {return Arrays.copyOf(elementData, size);}/*** 將ArrayList里面的元素賦值到一個數組中去* a的長度小于ArrayList的長度,直接調用Arrays類的copyOf* a的長度大于ArrayList的長度,調用System.arraycopy,然后把size位置賦值為空。* * @param a* 如果它的長度大的話,列表元素存儲在這個數組中; 否則分配一個新數組。* @return 一個包含ArrayList元素的數組* @throws ArrayStoreException* 將與數組類型不兼容的值賦值給數組元素時拋出的異常* @throws NullPointerException* 數組為空*/@SuppressWarnings("unchecked")public <T> T[] toArray(T[] a) {if (a.length < size)// 創建一個新的a的運行時類型數組,內容不變return (T[]) Arrays.copyOf(elementData, size, a.getClass());System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;}/*** 返回指定位置的值* @param index* @return*/@SuppressWarnings("unchecked")E elementData(int index) {return (E) elementData[index];}/*** 返回指定位置的值,先檢查是否超出數組長度* * @param index* 元素的索引* @return ArrayList中指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E get(int index) {// 檢查是否越界rangeCheck(index);// 返回ArrayList的elementData數組index位置的元素return elementData(index);}/*** 設置指定位置為一個新值,返回之前的值* * @param index* 要替換的元素的索引* @param element* 要存儲在指定位置的元素* @return 之前在指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E set(int index, E element) {// 檢查越界rangeCheck(index);// 獲取當前位置的值E oldValue = elementData(index);// 將element賦值到index位置elementData[index] = element;return oldValue;}/*** 添加一個值,首先會確保容量* * @param e* 要添加到此列表中的元素* @return <tt>true</tt> (as specified by {@link Collection#add})*/public boolean add(E e) {// 擴容ensureCapacityInternal(size + 1);// 將e賦值給elementData的size+1的位置elementData[size++] = e;return true;}/*** index位置添加元素element,會檢查添加的位置和容量* * @param index* 指定元素將被插入的索引* @param element* 要插入的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public void add(int index, E element) {// 判斷越界rangeCheckForAdd(index);// 擴容ensureCapacityInternal(size + 1); // Increments modCount!!// 將elementData從index位置開始,復制到elementData的index+1開始的連續空間System.arraycopy(elementData, index, elementData, index + 1,size - index);// 在index位置賦值elementelementData[index] = element;// ArrayList的大小++size++;}/*** 移除index位置的元素,會檢查去除的位置* * @param index* 要刪除的元素的索引* @return 刪除的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E remove(int index) {// 判斷越界rangeCheck(index);modCount++;// 讀取舊值E oldValue = elementData(index);// 獲取index位置開始到最后一個位置的個數int numMoved = size - index - 1;if (numMoved > 0)// index+1位置開始拷貝到從index開始的空間System.arraycopy(elementData, index + 1, elementData, index,numMoved);elementData[--size] = null; // 便于垃圾回收器回收return oldValue;}/*** 移除對象為O的元素,跟indexOf方法思想基本一致* @param o* 要從該列表中刪除的元素(如果存在)* @return true 如果這個列表包含指定的元素*/public boolean remove(Object o) {if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {fastRemove(index);return true;}} else {for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;}/*** 快速刪除指定位置的值,不需要檢查和返回值* * @param 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; // 便于垃圾回收器回收}/*** 清空數組,把每一個值設為null,方便垃圾回收(不同于reset,數組默認大小有改變的話不會重置)*/public void clear() {modCount++;// 便于垃圾回收器回收for (int i = 0; i < size; i++)elementData[i] = null;size = 0;}/*** 添加一個集合的元素到末端* * @param c* 包含要添加到此列表中的元素的集合* @return true 如果該列表因添加而改變* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(Collection<? extends E> c) {// c轉換為數組aObject[] a = c.toArray();// a占的內存空間長度賦值給numNewint numNew = a.length;// 擴容至size + numNewensureCapacityInternal(size + numNew);// 將a的第0位開始拷貝至elementData的size位開始,拷貝長度為numNewSystem.arraycopy(a, 0, elementData, size, numNew);// 將size增加numNewsize += numNew;return numNew != 0;}/*** 從第index位開始,將c全部拷貝到ArrayList* * @param index* 在哪個索引開始插入* @param c* 包含要添加到此列表中的元素的集合* @return true 如果該列表因添加而改變* @throws IndexOutOfBoundsException* {@inheritDoc}* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);// 將c轉換為數組aObject[] a = c.toArray();int numNew = a.length;// 擴容至size + numNewensureCapacityInternal(size + numNew);// 獲取需要添加的個數int numMoved = size - index;if (numMoved > 0)System.arraycopy(elementData, index, elementData, index + numNew,numMoved);System.arraycopy(a, 0, elementData, index, numNew);size += numNew;return numNew != 0;}/*** 刪除指定范圍元素。* * @throws IndexOutOfBoundsException* if {@code fromIndex} or {@code toIndex} is out of range ({@code fromIndex < 0 ||* fromIndex >= size() || toIndex > size() || toIndex <* fromIndex})*/protected void removeRange(int fromIndex, int toIndex) {modCount++;int numMoved = size - toIndex;// 后段保留的長度System.arraycopy(elementData, toIndex, elementData, fromIndex,numMoved);// 便于垃圾回收int newSize = size - (toIndex - fromIndex);for (int i = newSize; i < size; i++) {elementData[i] = null;}size = newSize;}/*** 檢查index是否超出數組長度*/private void rangeCheck(int index) {// 如果下標超過ArrayList的數組長度if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 檢查是否溢出*/private void rangeCheckForAdd(int index) {if (index > size || index < 0)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 拋出的異常的詳情*/private String outOfBoundsMsg(int index) {return "Index: " + index + ", Size: " + size;}/*** ArrayList移除集合c中的所有元素* * @param c* 包含要從此列表中移除的元素的集合* @return {@code true} 如果該列表因移除而改變* @throws ClassCastException* if the class of an element of this list is incompatible with* the specified collection (<a* href="Collection.html#optional-restrictions">optional</a>)* @throws NullPointerException* if this list contains a null element and the specified* collection does not permit null elements (<a* href="Collection.html#optional-restrictions">optional</a>),* or if the specified collection is null* @see Collection#contains(Object)*/public boolean removeAll(Collection<?> c) {// 如果c為空,則拋出空指針異常Objects.requireNonNull(c);// 調用batchRemove移除c中的元素return batchRemove(c, false);}/*** 僅保留指定集合c中的元素* * @param c* collection containing elements to be retained in this list* @return {@code true} if this list changed as a result of the call* @throws ClassCastException* if the class of an element of this list is incompatible with* the specified collection (<a* href="Collection.html#optional-restrictions">optional</a>)* @throws NullPointerException* if this list contains a null element and the specified* collection does not permit null elements (<a* href="Collection.html#optional-restrictions">optional</a>),* or if the specified collection is null* @see Collection#contains(Object)*/public boolean retainAll(Collection<?> c) {Objects.requireNonNull(c);// 調用batchRemove保留c中的元素return batchRemove(c, true);}/*** 根據complement值,將ArrayList中包含c中元素的元素刪除或者保留* * @param c* @param complement* true時從數組保留指定集合中元素的值,為false時從數組刪除指定集合中元素的值。* @return 數組中重復的元素都會被刪除(而不是僅刪除一次或幾次),有任何刪除操作都會返回true*/private boolean batchRemove(Collection<?> c, boolean complement) {final Object[] elementData = this.elementData;// 定義一個w,一個r,兩個同時右移int r = 0, w = 0;boolean modified = false;try {// r先右移for (; r < size; r++)// 如果c中不包含elementData[r]這個元素if (c.contains(elementData[r]) == complement)// 則直接將r位置的元素賦值給w位置的元素,w自增elementData[w++] = elementData[r];} finally {// 防止拋出異常導致上面r的右移過程沒完成if (r != size) {// 將r未右移完成的位置的元素賦值給w右邊位置的元素System.arraycopy(elementData, r,elementData, w,size - r);// 修改w值增加size-rw += size - r;}// 如果有被覆蓋掉的元素,則將w后面的元素都賦值為nullif (w != size) {// clear to let GC do its workfor (int i = w; i < size; i++)elementData[i] = null;modCount += size - w;// 改變的次數// 新的大小為保留的元素的個數size = w;modified = true;}}return modified;}/*** 保存數組實例的狀態到一個流(即序列化)。寫入過程數組被更改會拋出異常* * @serialData The length of the array backing the <tt>ArrayList</tt>* instance is emitted (int), followed by all of its elements* (each an <tt>Object</tt>) in the proper order.*/private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {// Write out element count, and any hidden stuffint expectedModCount = modCount;// 執行默認的反序列化/序列化過程。將當前類的非靜態和非瞬態字段寫入此流s.defaultWriteObject();// 寫入大小s.writeInt(size);// 寫入所有元素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;// 執行默認的序列化/反序列化過程s.defaultReadObject();// 讀入數組長度s.readInt(); // ignoredif (size > 0) {int capacity = calculateCapacity(elementData, size);SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);ensureCapacityInternal(size);Object[] a = elementData;// 讀入所有元素for (int i = 0; i < size; i++) {a[i] = s.readObject();}}}/*** 返回一個從index開始的ListIterator對象* * @throws IndexOutOfBoundsException* {@inheritDoc}*/public ListIterator<E> listIterator(int index) {if (index < 0 || index > size)throw new IndexOutOfBoundsException("Index: " + index);return new ListItr(index);}/*** 返回一個ListIterator對象,ListItr為ArrayList的一個內部類,實現了ListIterator<E> 接口* * @see #listIterator(int)*/public ListIterator<E> listIterator() {return new ListItr(0);}/*** 返回一個Iterator對象,Itr為ArrayList的一個內部類,實現了Iterator<E>接口* * @return an iterator over the elements in this list in proper sequence*/public Iterator<E> iterator() {return new Itr();}/*** 通用的迭代器實現*/private class Itr implements Iterator<E> {int cursor; // 下一個元素的索引,默認為0int lastRet = -1; // 上次訪問的元素的位置int expectedModCount = modCount;// 迭代過程修改數組拋出異常// 是否還有下一個public boolean hasNext() {return cursor != size;}// 下一個元素@SuppressWarnings("unchecked")public E next() {checkForComodification();// 檢查數組是否被修改int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;// 向后移動游標return (E) elementData[lastRet = i];// 設置訪問的位置并返回這個值}// 刪除元素public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();// 檢查數組是否被修改try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}@Override@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = ArrayList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[i++]);}// update once at end of iteration to reduce heap write trafficcursor = i;lastRet = i - 1;checkForComodification();}// 檢查數組是否被修改final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}/*** ListIterator迭代器實現*/private class ListItr extends Itr implements ListIterator<E> {ListItr(int index) {super();cursor = index;}public boolean hasPrevious() {return cursor != 0;}public int nextIndex() {return cursor;}public int previousIndex() {return cursor - 1;}@SuppressWarnings("unchecked")public E previous() {checkForComodification();int i = cursor - 1;if (i < 0)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i;return (E) elementData[lastRet = i];}public void set(E e) {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.set(lastRet, e);} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}public void add(E e) {checkForComodification();try {int i = cursor;ArrayList.this.add(i, e);cursor = i + 1;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}}/*** * 該方法返回的是父list的一個視圖,fromIndex(包含)到toIndex(不包含)。fromIndex=toIndex 表示子list為空*/public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);}/*** 安全檢查* * @param fromIndex* @param toIndex* @param size*/static void subListRangeCheck(int fromIndex, int toIndex, int size) {if (fromIndex < 0)throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);if (toIndex > size)throw new IndexOutOfBoundsException("toIndex = " + toIndex);if (fromIndex > toIndex)throw new IllegalArgumentException("fromIndex(" + fromIndex +") > toIndex(" + toIndex + ")");}/*** 子數組*/private class SubList extends AbstractList<E> implements RandomAccess {private final AbstractList<E> parent;private final int parentOffset;private final int offset;int size;SubList(AbstractList<E> parent,int offset, int fromIndex, int toIndex) {this.parent = parent;this.parentOffset = fromIndex;this.offset = offset + fromIndex;this.size = toIndex - fromIndex;this.modCount = ArrayList.this.modCount;}public E set(int index, E e) {rangeCheck(index);checkForComodification();E oldValue = ArrayList.this.elementData(offset + index);ArrayList.this.elementData[offset + index] = e;return oldValue;}public E get(int index) {rangeCheck(index);checkForComodification();return ArrayList.this.elementData(offset + index);}public int size() {checkForComodification();return this.size;}public void add(int index, E e) {rangeCheckForAdd(index);checkForComodification();parent.add(parentOffset + index, e);this.modCount = parent.modCount;this.size++;}public E remove(int index) {rangeCheck(index);checkForComodification();E result = parent.remove(parentOffset + index);this.modCount = parent.modCount;this.size--;return result;}protected void removeRange(int fromIndex, int toIndex) {checkForComodification();parent.removeRange(parentOffset + fromIndex,parentOffset + toIndex);this.modCount = parent.modCount;this.size -= toIndex - fromIndex;}public boolean addAll(Collection<? extends E> c) {return addAll(this.size, c);}public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);int cSize = c.size();if (cSize == 0)return false;checkForComodification();parent.addAll(parentOffset + index, c);this.modCount = parent.modCount;this.size += cSize;return true;}public Iterator<E> iterator() {return listIterator();}public ListIterator<E> listIterator(final int index) {checkForComodification();rangeCheckForAdd(index);final int offset = this.offset;return new ListIterator<E>() {int cursor = index;int lastRet = -1;int expectedModCount = ArrayList.this.modCount;public boolean hasNext() {return cursor != SubList.this.size;}@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= SubList.this.size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (offset + i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[offset + (lastRet = i)];}public boolean hasPrevious() {return cursor != 0;}@SuppressWarnings("unchecked")public E previous() {checkForComodification();int i = cursor - 1;if (i < 0)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (offset + i >= elementData.length)throw new ConcurrentModificationException();cursor = i;return (E) elementData[offset + (lastRet = i)];}@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = SubList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (offset + i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[offset + (i++)]);}// update once at end of iteration to reduce heap write// trafficlastRet = cursor = i;checkForComodification();}public int nextIndex() {return cursor;}public int previousIndex() {return cursor - 1;}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {SubList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = ArrayList.this.modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}public void set(E e) {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.set(offset + lastRet, e);} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}public void add(E e) {checkForComodification();try {int i = cursor;SubList.this.add(i, e);cursor = i + 1;lastRet = -1;expectedModCount = ArrayList.this.modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}final void checkForComodification() {if (expectedModCount != ArrayList.this.modCount)throw new ConcurrentModificationException();}};}/*** 返回指定范圍的子數組* * @param fromIndex* @param toIndex* @return*/public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, offset, fromIndex, toIndex);}private void rangeCheck(int index) {if (index < 0 || index >= this.size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}private void rangeCheckForAdd(int index) {if (index < 0 || index > this.size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}private String outOfBoundsMsg(int index) {return "Index: " + index + ", Size: " + this.size;}private void checkForComodification() {if (ArrayList.this.modCount != this.modCount)throw new ConcurrentModificationException();}public Spliterator<E> spliterator() {checkForComodification();return new ArrayListSpliterator<E>(ArrayList.this, offset,offset + this.size, this.modCount);}}/*** Java 8 lambda 使用流遍歷數組*/@Overridepublic void forEach(Consumer<? super E> action) {Objects.requireNonNull(action);final int expectedModCount = modCount;@SuppressWarnings("unchecked") final E[] elementData = (E[]) this.elementData;final int size = this.size;for (int i = 0; modCount == expectedModCount && i < size; i++) {action.accept(elementData[i]);}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}}/*** 為了并行遍歷元素而設計的一個迭代器* @return a {@code Spliterator} over the elements in this list* @since 1.8*/@Overridepublic Spliterator<E> spliterator() {return new ArrayListSpliterator<>(this, 0, -1, 0);}/*** Index-based split-by-two, lazily initialized Spliterator*/static final class ArrayListSpliterator<E> implements Spliterator<E> {/**
//forEach()private final ArrayList<E> list;private int index; // current index, modified on advance/splitprivate int fence; // -1 until used; then one past last indexprivate int expectedModCount; // initialized when fence set/*** Create new spliterator covering the given range*/ArrayListSpliterator(ArrayList<E> list, int origin, int fence,int expectedModCount) {this.list = list; // OK if null unless traversedthis.index = origin;this.fence = fence;this.expectedModCount = expectedModCount;}private int getFence() { // initialize fence to size on first useint hi; // (a specialized variant appears in method forEach)ArrayList<E> lst;if ((hi = fence) < 0) {if ((lst = list) == null)hi = fence = 0;else {expectedModCount = lst.modCount;hi = fence = lst.size;}}return hi;}public ArrayListSpliterator<E> trySplit() {int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;return (lo >= mid) ? null : // divide range in half unless too smallnew ArrayListSpliterator<E>(list, lo, index = mid,expectedModCount);}public boolean tryAdvance(Consumer<? super E> action) {if (action == null)throw new NullPointerException();int hi = getFence(), i = index;if (i < hi) {index = i + 1;@SuppressWarnings("unchecked") E e = (E) list.elementData[i];action.accept(e);if (list.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}return false;}public void forEachRemaining(Consumer<? super E> action) {int i, hi, mc; // hoist accesses and checks from loopArrayList<E> lst;Object[] a;if (action == null)throw new NullPointerException();if ((lst = list) != null && (a = lst.elementData) != null) {if ((hi = fence) < 0) {mc = lst.modCount;hi = lst.size;} elsemc = expectedModCount;if ((i = index) >= 0 && (index = hi) <= a.length) {for (; i < hi; ++i) {@SuppressWarnings("unchecked") E e = (E) a[i];action.accept(e);}if (lst.modCount == mc)return;}}throw new ConcurrentModificationException();}public long estimateSize() {return (long) (getFence() - index);}public int characteristics() {return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;}}@Overridepublic boolean removeIf(Predicate<? super E> filter) {Objects.requireNonNull(filter);// figure out which elements are to be removed// any exception thrown from the filter predicate at this stage// will leave the collection unmodifiedint removeCount = 0;final BitSet removeSet = new BitSet(size);final int expectedModCount = modCount;final int size = this.size;for (int i = 0; modCount == expectedModCount && i < size; i++) {@SuppressWarnings("unchecked") final E element = (E) elementData[i];if (filter.test(element)) {removeSet.set(i);removeCount++;}}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}// shift surviving elements left over the spaces left by removed// elementsfinal boolean anyToRemove = removeCount > 0;if (anyToRemove) {final int newSize = size - removeCount;for (int i = 0, j = 0; (i < size) && (j < newSize); i++, j++) {i = removeSet.nextClearBit(i);elementData[j] = elementData[i];}for (int k = newSize; k < size; k++) {elementData[k] = null; // Let gc do its work}this.size = newSize;if (modCount != expectedModCount) {throw new ConcurrentModificationException();}modCount++;}return anyToRemove;}@Override@SuppressWarnings("unchecked")public void replaceAll(UnaryOperator<E> operator) {Objects.requireNonNull(operator);final int expectedModCount = modCount;final int size = this.size;for (int i = 0; modCount == expectedModCount && i < size; i++) {elementData[i] = operator.apply((E) elementData[i]);}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}modCount++;}@Override@SuppressWarnings("unchecked")public void sort(Comparator<? super E> c) {final int expectedModCount = modCount;Arrays.sort((E[]) elementData, 0, size, c);if (modCount != expectedModCount) {throw new ConcurrentModificationException();}modCount++;}
}
LinkedList
java.lang.Objectjava.util.AbstractCollection<E>java.util.AbstractList<E>java.util.AbstractSequentialList<E>java.util.LinkedList<E>
List?接口的鏈接列表實現。實現所有可選的列表操作,并且允許所有元素(包括?null)。
除了實現?List?接口外,LinkedList?類還為在列表的開頭及結尾?get、remove?和?insert?元素提供了統一的命名方法。這些操作允許將鏈接列表用作堆棧、隊列或雙端隊列。
此類實現?Deque?接口,為?add、poll?提供先進先出隊列操作,以及其他堆棧和雙端隊列操作。
所有操作都是按照雙重鏈接列表的需要執行的。在列表中編索引的操作將從開頭或結尾遍歷列表(從靠近指定索引的一端)。
操作效率:大部分效率都是o(n)的
同步:
注意,此實現不是同步的。如果多個線程同時訪問一個鏈接列表,而其中至少一個線程從結構上修改了該列表,則它必須?保持外部同步。(結構修改指添加或刪除一個或多個元素的任何操作;僅設置元素的值不是結構修改。)這一般通過對自然封裝該列表的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用?Collections.synchronizedList
?方法來“包裝”該列表。最好在創建時完成這一操作,以防止對列表進行意外的不同步訪問,如下所示:
List list = Collections.synchronizedList(new LinkedList(...));
iterator :
此類的?iterator?和?listIterator?方法返回的迭代器是快速失敗?的:在迭代器創建之后,如果從結構上對列表進行修改,除非通過迭代器自身的?remove?或?add?方法,其他任何時間任何方式的修改,迭代器都將拋出?ConcurrentModificationException
。因此,面對并發的修改,迭代器很快就會完全失敗,而不冒將來不確定的時間任意發生不確定行為的風險。
注意,迭代器的快速失敗行為不能得到保證,一般來說,存在不同步的并發修改時,不可能作出任何硬性保證。快速失敗迭代器盡最大努力拋出?ConcurrentModificationException。因此,編寫依賴于此異常的程序的方式是錯誤的,正確做法是:迭代器的快速失敗行為應該僅用于檢測程序錯誤。
源碼解析
package java.util;
import java.util.function.Consumer;
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable {/*** 元素數量*/transient int size = 0;/*** 首結點引用*/transient Node<E> first;/*** 尾節點引用*/transient Node<E> last;/*** 無參構造方法*/public LinkedList() {}/*** 通過一個集合初始化,元素順序有這個集合的迭代器返回順序決定* * @param c* 其元素將被放入此列表中的集合* @throws NullPointerException* 如果指定的集合是空的*/public LinkedList(Collection<? extends E> c) {// 調用無參構造this();// 添加所有的元素addAll(c);}/*** 頭插,內部使用*/private void linkFirst(E e) {// 當前首結點final Node<E> f = first;// 構建新節點final Node<E> newNode = new Node<>(null, e, f);// 將newNode作為首節點first = newNode;// 如果原首節點為null,即原鏈表為null,則鏈表尾節點也設置為newNodeif (f == null)last = newNode;else // 否則,原首節點的prev設置為newNodef.prev = newNode;size++; // 長度+1modCount++; // 修改次數+1}/*** 尾插*/void linkLast(E e) {// 獲取尾結點final Node<E> l = last;// 構建新節點final Node<E> newNode = new Node<>(l, e, null);// newNode作為尾節點last = newNode;// 如果原尾節點為null,即原鏈表為null,則鏈表首節點也設置為newNodeif (l == null)first = newNode;else // 否則,原尾節點的next設置為newNodel.next = newNode;size++;modCount++;}/*** 在非空節點succ前插入節點值e*/void linkBefore(E e, Node<E> succ) {final Node<E> pred = succ.prev;// 構建新節點final Node<E> newNode = new Node<>(pred, e, succ);// 設置newNode為succ的前節點succ.prev = newNode;// 如果succ.prev為null,即succ為首節點,則將newNode設置為首節點if (pred == null)first = newNode;else // 如果succ不是首節點pred.next = newNode;size++;modCount++;}/*** 刪除首結點,返回存儲的元素,內部使用*/private E unlinkFirst(Node<E> f) {// 獲取首結點存儲的元素final E element = f.item;// 獲取首結點的后繼結點final Node<E> next = f.next;// 刪除首結點f.item = null;f.next = null; // 便于垃圾回收// 首結點后繼結點設為首結點first = next;// 如果原來首結點的后繼結點為空,則尾結點設為null// 否則,原來首結點的后繼結點的前驅結點設為nullif (next == null)last = null;elsenext.prev = null;size--;modCount++;// 返回原來首結點存儲的元素return element;}/*** 刪除尾結點,返回存儲的元素,內部使用*/private E unlinkLast(Node<E> l) {// 獲取尾結點存儲的元素final E element = l.item;// 獲取尾結點的前驅結點final Node<E> prev = l.prev;// 刪除尾結點l.item = null;l.prev = null; // help GC// 原來尾結點的前驅結點設為尾結點last = prev;// 如果原來尾結點的前驅結點為空,則首結點設為null// 否則,原來尾結點的前驅結點的后繼結點設為nullif (prev == null)first = null;elseprev.next = null;size--;modCount++;// 返回原來尾結點存儲的元素return element;}/*** 刪除指定非空結點,返回存儲的元素*/E unlink(Node<E> x) {// 獲取指定非空結點存儲的元素final E element = x.item;// 獲取指定非空結點的后繼結點final Node<E> next = x.next;// 獲取指定非空結點的前驅結點final Node<E> prev = x.prev;/*** 如果指定非空結點的前驅結點為空,則指定非空結點的后繼結點設為首結點 * 否則,指定非空結點的后繼結點設為指定非空結點的前驅結點的后繼結點,* 指定非空結點的前驅結點設為null*/if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}/*** 如果指定非空結點的后繼結點為空,則指定非空結點的前驅結點設為尾結點 * 否則,指定非空結點的前驅結點設為指定非空結點的后繼結點的前驅結點,* 指定非空結點的后繼結點設為null*/if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}// 指定非空結點存儲的元素設為nullx.item = null;size--;modCount++;// 返回指定非空結點存儲的元素return element;}/*** 獲取首結點存儲的元素* * @return 首結點存儲的元素* @throws NoSuchElementException* 如果鏈表為空*/public E getFirst() {// 獲取首結點引用final Node<E> f = first;// 如果首結點為空,則拋出無該元素異常if (f == null)throw new NoSuchElementException();// 返回首結點存儲的元素return f.item;}/*** 獲取尾結點存儲的元素* * @return 尾結點存儲的元素* @throws NoSuchElementException* 如果鏈表為空*/public E getLast() {// 獲取尾結點引用final Node<E> l = last;// 如果尾結點為空,則拋出無該元素異常if (l == null)throw new NoSuchElementException();// 返回尾結點存儲的元素return l.item;}/*** 刪除首結點,返回存儲的元素* * @return 首結點存儲的元素* @throws NoSuchElementException* 如果鏈表為空*/public E removeFirst() {// 獲取首結點引用final Node<E> f = first;// 如果首結點為空,則拋出無該元素異常if (f == null)throw new NoSuchElementException();// 刪除首結點,返回存儲的元素return unlinkFirst(f);}/*** 刪除尾結點,返回存儲的元素* * @return 尾結點存儲的元素* @throws NoSuchElementException* 如果鏈表為空*/public E removeLast() {// 獲取尾結點引用final Node<E> l = last;// 如果尾結點為空,則拋出無該元素異常if (l == null)throw new NoSuchElementException();// 刪除尾結點,返回存儲的元素return unlinkLast(l);}/*** 頭部插入指定元素* * @param e* 要添加的元素*/public void addFirst(E e) {// 通過頭插法來插入指定元素linkFirst(e);}/*** 尾部插入指定元素,該方法等價于add()* * @param e* the element to add*/public void addLast(E e) {linkLast(e);}/*** 判斷是否包含指定元素* * @param o* 判斷鏈表是否包含的元素* @return {@code true} 如果鏈表包含指定的元素*/public boolean contains(Object o) {// 返回指定元素的索引位置,不存在就返回-1,然后比較返回bool值return indexOf(o) != -1;}/*** 獲取元素數量* * @return 元素數量*/public int size() {return size;}/*** 插入指定元素,返回操作結果,默認添加到末尾作為最后一個元素* * @param e* 要添加到此鏈表中的元素* @return {@code true} (as specified by {@link Collection#add})*/public boolean add(E e) {// 通過尾插法來插入指定元素linkLast(e);return true;}/*** 刪除指定元素,默認從first節點開始,刪除第一次出現的那個元素* * @param o* 要從該列表中刪除的元素(如果存在)* @return {@code true} 如果這個列表包含指定的元素*/public boolean remove(Object o) {// 會根據是否為null分開處理。若值不是null,會用到對象的equals()方法if (o == null) {// 遍歷鏈表,查找到指定元素后刪除該結點,返回truefor (Node<E> x = first; x != null; x = x.next) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) {unlink(x);return true;}}}// 查找失敗return false;}/*** 將集合插入到鏈表尾部* * @param c* 包含要添加到此鏈表中的元素的集合* @return {@code true} 如果該鏈表因添加而改變* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(Collection<? extends E> c) {return addAll(size, c);}/*** 將集合從指定位置開始插入* * @param index* 在哪個索引處前插入指定集合中的第一個元素* @param c* 包含要添加到此鏈表中的元素的集合* @return {@code true} 如果該鏈表因添加而改變* @throws IndexOutOfBoundsException* {@inheritDoc}* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(int index, Collection<? extends E> c) {// 檢查索引是否正確(0<=index<=size)checkPositionIndex(index);// 得到元素數組Object[] a = c.toArray();// 得到元素個數int numNew = a.length;// 沒有元素,返回falseif (numNew == 0)return false;// succ指向當前需要插入節點的位置,pred指向其前一個節點Node<E> pred, succ;// 末尾開始添加,當前節點后一個節點為null,前一個節點為尾節點if (index == size) {succ = null;pred = last;} else { //當前位置的節點為指定位置的節點,前一個節點為要添加的節點的前一個節點succ = node(index);pred = succ.prev;}// 遍歷數組并添加到列表中for (Object o : a) {@SuppressWarnings("unchecked") E e = (E) o;// “封裝”一個新節點Node<E> newNode = new Node<>(pred, e, null);// 原鏈表為null,新插入的節點作為鏈表首節點if (pred == null)first = newNode;elsepred.next = newNode; // 存在前節點,前節點向后指向新加的節點pred = newNode; // pred指針向后移動}// 從最后開始添加,則新節點成為尾節點if (succ == null) {last = pred;} else {pred.next = succ; // 新節點向后指向之前得到的后續第一個節點succ.prev = pred; // 后續的第一個節點也應改為向前指向最后一個添加的節點}size += numNew;modCount++;return true;}/*** 刪除所有元素*/public void clear() {// 遍歷鏈表,刪除所有結點,方便gc回收垃圾for (Node<E> x = first; x != null; ) {Node<E> next = x.next;x.item = null;x.next = null;x.prev = null;x = next;}// 首尾結點置空first = last = null;// 元素數量置0size = 0;modCount++;}// 位置訪問操作/*** 獲取指定位置的元素* * @param index* 要返回的元素的索引* @return 該鏈表中指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E get(int index) {// 判斷指定位置是否合法checkElementIndex(index);// 返回指定位置的元素return node(index).item;}/*** 修改指定位置的元素,返回之前元素* * @param index* 要替換的元素的索引* @param element* 要存儲在指定位置的元素* @return 之前在指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E set(int index, E element) {// 判斷指定位置是否合法checkElementIndex(index);// 獲取指定位置的結點Node<E> x = node(index);// 獲取該結點存儲的元素E oldVal = x.item;// 修改該結點存儲的元素x.item = element;// 返回該結點存儲的之前的元素return oldVal;}/*** 在指定位置前插入指定元素* 頭插法* @param index* 指定元素將被插入的索引* @param element* 要插入的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public void add(int index, E element) {// 判斷指定位置是否合法checkPositionIndex(index);// 如果指定位置在尾部,則通過尾插法來插入指定元素if (index == size)linkLast(element);else // 如果指定位置不是尾部,則添加到指定位置前linkBefore(element, node(index));}/*** 刪除指定位置的元素,返回之前元素* * @param index* 要刪除的元素的索引* @return 之前在指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E remove(int index) {// 判斷指定位置是否合法checkElementIndex(index);// 刪除指定位置的結點,返回之前元素return unlink(node(index));}/*** 判斷指定位置是否合法*/private boolean isElementIndex(int index) {return index >= 0 && index < size;}/*** 判斷迭代器遍歷時或插入元素時指定位置是否合法*/private boolean isPositionIndex(int index) {return index >= 0 && index <= size;}/*** 獲取越界異常信息*/private String outOfBoundsMsg(int index) {return "Index: " + index + ", Size: " + size;}/*** 判斷指定位置是否合法* * @param index*/private void checkElementIndex(int index) {if (!isElementIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 判斷指定位置是否合法* * @param index*/private void checkPositionIndex(int index) {if (!isPositionIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 獲取指定下標的結點*/Node<E> node(int index) {// 如果指定下標<一半元素數量,則從首結點開始遍歷// 否則,從尾結點開始遍歷if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}// 查詢操作/*** 獲取首次出現指定元素的位置 -1表示不存在* 同樣是根據是否為null進行區分* @param o* 要查找的元素* @return the index of the first occurrence of the specified element in* this list, or -1 if this list does not contain the element*/public int indexOf(Object o) {int index = 0;if (o == null) {// 遍歷鏈表,順序查找指定元素for (Node<E> x = first; x != null; x = x.next) {if (x.item == null)return index;index++;}} else {for (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item))return index;index++;}}return -1;}/*** 獲取逆序下首次出現指定元素的位置 -1表示不存在* * @param o* 要查找的元素* @return the index of the last occurrence of the specified element in this* list, or -1 if this list does not contain the element*/public int lastIndexOf(Object o) {int index = size;if (o == null) {// 遍歷鏈表,逆序查找指定元素for (Node<E> x = last; x != null; x = x.prev) {index--;if (x.item == null)return index;}} else {for (Node<E> x = last; x != null; x = x.prev) {index--;if (o.equals(x.item))return index;}}return -1;}// 隊列操作/*** 出隊(從前端),獲得第一個元素,不存在會返回null,不會刪除元素(節點) 獲取首元素* * @return the head of this list, or {@code null} 如果鏈表為空* @since 1.5*/public E peek() {final Node<E> f = first;// 如果首結點為空,則返回null// 否則,返回首結點存儲的元素return (f == null) ? null : f.item;}/*** 出隊(從前端),不刪除元素,若為null會拋出異常而不是返回null 獲取首元素* * @return the head of this list* @throws NoSuchElementException* 如果鏈表為空* @since 1.5*/public E element() {// 返回首結點存儲的元素return getFirst();}/*** 出隊(從前端),如果不存在會返回null,存在的話會返回值并移除這個元素(節點) 獲取并刪除首元素* * @return the head of this list, or {@code null} 如果鏈表為空* @since 1.5*/public E poll() {// 獲取首結點引用final Node<E> f = first;// 如果首結點為空,則返回null// 否則,刪除首結點,返回首結點存儲的元素return (f == null) ? null : unlinkFirst(f);}/*** 出隊(從前端),如果不存在會拋出異常而不是返回null,存在的話會返回值并移除這個元素(節點) 獲取并刪除首元素* * @return the head of this list* @throws NoSuchElementException* 如果鏈表為空* @since 1.5*/public E remove() {// 刪除首結點,返回首結點存儲的元素return removeFirst();}/*** 入隊(從后端),始終返回true* * 鏈表不會溢出* @param e* the element to add* @return {@code true} (as specified by {@link Queue#offer})* @since 1.5*/public boolean offer(E e) {// 通過尾插法插入指定元素,返回操作結果return add(e);}// 雙端隊列操作/*** 入隊(從前端),始終返回true* * @param e* 要插入的元素* @return {@code true} (as specified by {@link Deque#offerFirst})* @since 1.6*/public boolean offerFirst(E e) {// 通過頭插法來插入指定元素addFirst(e);return true;}/*** 入隊(從后端),始終返回true* * @param e* 要插入的元素* @return {@code true} (as specified by {@link Deque#offerLast})* @since 1.6*/public boolean offerLast(E e) {// 通過尾插法來插入指定元素addLast(e);return true;}/*** 出隊(從前端),獲得第一個元素,不存在會返回null,不會刪除元素(節點)* * @return the first element of this list, or {@code null} 如果鏈表為空* @since 1.6*/public E peekFirst() {// 獲取首結點引用final Node<E> f = first;// 如果首結點為空,則返回null// 否則,返回首結點存儲的元素return (f == null) ? null : f.item;}/*** 出隊(從后端),獲得最后一個元素,不存在會返回null,不會刪除元素(節點)* * @return the last element of this list, or {@code null} 如果鏈表為空* @since 1.6*/public E peekLast() {// 獲取尾結點引用final Node<E> l = last;// 如果尾結點為空,則返回null// 否則,返回尾結點存儲的元素return (l == null) ? null : l.item;}/*** 出隊(從前端),獲得第一個元素,不存在會返回null,會刪除元素(節點)* * @return the first element of this list, or {@code null} if this list is* empty* @since 1.6*/public E pollFirst() {// 獲取首結點引用final Node<E> f = first;// 如果首結點為空,則返回null// 否則,刪除首結點,返回首結點存儲的元素return (f == null) ? null : unlinkFirst(f);}/*** 出隊(從后端),獲得最后一個元素,不存在會返回null,會刪除元素(節點)* * @return the last element of this list, or {@code null} if this list is* empty* @since 1.6*/public E pollLast() {// 獲取尾結點引用final Node<E> l = last;// 如果尾結點為空,則返回null// 否則,刪除尾結點,返回尾結點存儲的元素return (l == null) ? null : unlinkLast(l);}/*** 入棧,從前面添加* * @param e* the element to push* @since 1.6*/public void push(E e) {// 通過頭插法來插入指定元素addFirst(e);}/*** 出棧,返回棧頂元素,從前面移除(會刪除)* * @return the element at the front of this list (which is the top of the* stack represented by this list)* @throws NoSuchElementException* 如果鏈表為空* @since 1.6*/public E pop() {// 刪除首結點,返回首結點存儲的元素return removeFirst();}/*** 刪除順序下首次出現的指定元素,返回操作結果* * @param o* 要從該列表中刪除的元素(如果存在)* @return {@code true} 如果鏈表包含指定的元素* @since 1.6*/public boolean removeFirstOccurrence(Object o) {// 刪除順序下首次出現的指定元素對應的結點,返回操作結果return remove(o);}/*** 刪除逆序下首次出現的指定元素,返回操作結果* * @param o* 要從該列表中刪除的元素(如果存在)* @return {@code true} 如果鏈表包含指定的元素* @since 1.6*/public boolean removeLastOccurrence(Object o) {// 由于LinkedList中允許存放null,因此下面通過兩種情況來分別處理if (o == null) {// 遍歷鏈表,從尾結點開始查找指定元素// 如果查找成功,刪除該結點,返回truefor (Node<E> x = last; x != null; x = x.prev) {if (x.item == null) {unlink(x);return true;}}} else {for (Node<E> x = last; x != null; x = x.prev) {if (o.equals(x.item)) {unlink(x);return true;}}}// 查找失敗return false;}/*** Returns a list-iterator of the elements in this list (in proper* sequence), starting at the specified position in the list. Obeys the* general contract of {@code List.listIterator(int)}.* <p>* <p>* The list-iterator is <i>fail-fast</i>: if the list is structurally* modified at any time after the Iterator is created, in any way except* through the list-iterator's own {@code remove} or {@code add} methods,* the list-iterator will throw a {@code ConcurrentModificationException}.* Thus, in the face of concurrent modification, the iterator fails quickly* and cleanly, rather than risking arbitrary, non-deterministic behavior at* an undetermined time in the future.* * @param index* index of the first element to be returned from the* list-iterator (by a call to {@code next})* @return a ListIterator of the elements in this list (in proper sequence),* starting at the specified position in the list* @throws IndexOutOfBoundsException* {@inheritDoc}* @see List#listIterator(int)*/public ListIterator<E> listIterator(int index) {checkPositionIndex(index);return new ListItr(index);}private class ListItr implements ListIterator<E> {private Node<E> lastReturned;private Node<E> next;private int nextIndex;private int expectedModCount = modCount;ListItr(int index) {// assert isPositionIndex(index);next = (index == size) ? null : node(index);nextIndex = index;}public boolean hasNext() {return nextIndex < size;}public E next() {checkForComodification();if (!hasNext())throw new NoSuchElementException();lastReturned = next;next = next.next;nextIndex++;return lastReturned.item;}public boolean hasPrevious() {return nextIndex > 0;}public E previous() {checkForComodification();if (!hasPrevious())throw new NoSuchElementException();lastReturned = next = (next == null) ? last : next.prev;nextIndex--;return lastReturned.item;}public int nextIndex() {return nextIndex;}public int previousIndex() {return nextIndex - 1;}public void remove() {checkForComodification();if (lastReturned == null)throw new IllegalStateException();Node<E> lastNext = lastReturned.next;unlink(lastReturned);if (next == lastReturned)next = lastNext;elsenextIndex--;lastReturned = null;expectedModCount++;}public void set(E e) {if (lastReturned == null)throw new IllegalStateException();checkForComodification();lastReturned.item = e;}public void add(E e) {checkForComodification();lastReturned = null;if (next == null)linkLast(e);elselinkBefore(e, next);nextIndex++;expectedModCount++;}public void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (modCount == expectedModCount && nextIndex < size) {action.accept(next.item);lastReturned = next;next = next.next;nextIndex++;}checkForComodification();}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}/*** 節點的數據結構,包含前后節點的引用和當前節點* * @param <E>*/private static class Node<E> {// 存儲的元素E item;// 后繼結點Node<E> next;// 前驅結點Node<E> prev;// 前驅結點、存儲的元素和后繼結點作為參數的構造方法Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}/*** 返回迭代器* * @since 1.6*/public Iterator<E> descendingIterator() {return new DescendingIterator();}/*** 因為采用鏈表實現,所以迭代器很簡單*/private class DescendingIterator implements Iterator<E> {private final ListItr itr = new ListItr(size());public boolean hasNext() {return itr.hasPrevious();}public E next() {return itr.previous();}public void remove() {itr.remove();}}/*** 父類克隆方法*/@SuppressWarnings("unchecked")private LinkedList<E> superClone() {try {return (LinkedList<E>) super.clone();} catch (CloneNotSupportedException e) {throw new InternalError(e);}}/*** 克隆,淺拷貝* * 淺拷貝時,若存儲的是對象的引用,拷貝時,對象本身的改變將表現到副本中,而深拷貝不會。* @return a shallow copy of this {@code LinkedList} instance*/public Object clone() {LinkedList<E> clone = superClone();// 鏈表初始化clone.first = clone.last = null;clone.size = 0;clone.modCount = 0;// 插入結點for (Node<E> x = first; x != null; x = x.next)clone.add(x.item);// 返回克隆后的對象引用return clone;}/*** 返回新的數組,數組含有列表中所有元素*/public Object[] toArray() {Object[] result = new Object[size];int i = 0;for (Node<E> x = first; x != null; x = x.next)result[i++] = x.item;return result;}/*** Returns an array containing all of the elements in this list in proper* sequence (from first to last element); the runtime type of the returned* array is that of the specified array. If the list fits in the specified* array, it is returned therein. Otherwise, a new array is allocated with* the runtime type of the specified array and the size of this list.* <p>* <p>* If the list fits in the specified array with room to spare (i.e., the* array has more elements than the list), the element in the array* immediately following the end of the list is set to {@code null}. (This* is useful in determining the length of the list <i>only</i> if the* caller knows that the list does not contain any null elements.)* <p>* <p>* Like the {@link #toArray()} method, this method acts as bridge between* array-based and collection-based APIs. Further, this method allows* precise control over the runtime type of the output array, and may, under* certain circumstances, be used to save allocation costs.* <p>* <p>* Suppose {@code x} is a list known to contain only strings. The following* code can be used to dump the list into a newly allocated array of* {@code String}:* <p>* * <pre>* String[] y = x.toArray(new String[0]);* </pre>* * <p>* Note that {@code toArray(new Object[0])} is identical in function to* {@code toArray()}.* * @param a* the array into which the elements of the list are to be* stored, if it is big enough; otherwise, a new array of the* same runtime type is allocated for this purpose.* @return an array containing the elements of the list* @throws ArrayStoreException* if the runtime type of the specified array is not a supertype* of the runtime type of every element in this list* @throws NullPointerException* if the specified array is null*/@SuppressWarnings("unchecked")public <T> T[] toArray(T[] a) {if (a.length < size)a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);int i = 0;Object[] result = a;for (Node<E> x = first; x != null; x = x.next)result[i++] = x.item;if (a.length > size)a[size] = null;return a;}private static final long serialVersionUID = 876323262645176354L;/*** 序列化*/private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {// 默認序列化s.defaultWriteObject();// 寫入元素數量s.writeInt(size);// 遍歷鏈表,寫入所有元素for (Node<E> x = first; x != null; x = x.next)s.writeObject(x.item);}/*** 反序列化*/@SuppressWarnings("unchecked")private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {// 默認反序列化s.defaultReadObject();// 讀取元素數量int size = s.readInt();// 遍歷鏈表,讀取所有元素并尾部插入for (int i = 0; i < size; i++)linkLast((E) s.readObject());}/*** Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>* and <em>fail-fast</em> {@link Spliterator} over the elements in this* list.* <p>* <p>* The {@code Spliterator} reports {@link Spliterator#SIZED} and* {@link Spliterator#ORDERED}. Overriding implementations should document* the reporting of additional characteristic values.* * @return a {@code Spliterator} over the elements in this list* @implNote The {@code Spliterator} additionally reports* {@link Spliterator#SUBSIZED} and implements {@code trySplit} to* permit limited parallelism..* @since 1.8*/@Overridepublic Spliterator<E> spliterator() {return new LLSpliterator<E>(this, -1, 0);}/*** A customized variant of Spliterators.IteratorSpliterator*/static final class LLSpliterator<E> implements Spliterator<E> {static final int BATCH_UNIT = 1 << 10; // batch array size incrementstatic final int MAX_BATCH = 1 << 25; // max batch array size;final LinkedList<E> list; // null OK unless traversedNode<E> current; // current node; null until initializedint est; // size estimate; -1 until first neededint expectedModCount; // initialized when est setint batch; // batch size for splitsLLSpliterator(LinkedList<E> list, int est, int expectedModCount) {this.list = list;this.est = est;this.expectedModCount = expectedModCount;}final int getEst() {int s; // force initializationfinal LinkedList<E> lst;if ((s = est) < 0) {if ((lst = list) == null)s = est = 0;else {expectedModCount = lst.modCount;current = lst.first;s = est = lst.size;}}return s;}public long estimateSize() {return (long) getEst();}public Spliterator<E> trySplit() {Node<E> p;int s = getEst();if (s > 1 && (p = current) != null) {int n = batch + BATCH_UNIT;if (n > s)n = s;if (n > MAX_BATCH)n = MAX_BATCH;Object[] a = new Object[n];int j = 0;do {a[j++] = p.item;} while ((p = p.next) != null && j < n);current = p;batch = j;est = s - j;return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);}return null;}public void forEachRemaining(Consumer<? super E> action) {Node<E> p;int n;if (action == null) throw new NullPointerException();if ((n = getEst()) > 0 && (p = current) != null) {current = null;est = 0;do {E e = p.item;p = p.next;action.accept(e);} while (p != null && --n > 0);}if (list.modCount != expectedModCount)throw new ConcurrentModificationException();}public boolean tryAdvance(Consumer<? super E> action) {Node<E> p;if (action == null) throw new NullPointerException();if (getEst() > 0 && (p = current) != null) {--est;E e = p.item;current = p.next;action.accept(e);if (list.modCount != expectedModCount)throw new ConcurrentModificationException();return true;}return false;}public int characteristics() {return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;}}}
?
Vector
基于synchronized實現的線程安全的ArrayList,但在插入元素時容量擴充的機制和ArrayList稍有不同,并可通過傳入capacityIncrement來控制容量的擴充。
成員變量
protected Object[] elementData;
protected int elementCount;
protected int capacityIncrement;
構造方法
public Vector(int initialCapacity) {this(initialCapacity, 0);
}
public Vector() {this(10);
}
public Vector(int initialCapacity, int capacityIncrement) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);this.elementData = new Object[initialCapacity];this.capacityIncrement = capacityIncrement;
}
添加
public synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;
}
?
刪除
public boolean remove(Object o) {return removeElement(o);
}public synchronized boolean removeElement(Object obj) {modCount++;int i = indexOf(obj);if (i >= 0) {removeElementAt(i);return true;}return false;
}
擴容
private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);
}
獲取
public synchronized E get(int index) {if (index >= elementCount)throw new ArrayIndexOutOfBoundsException(index);return elementData(index);
}
更新
public synchronized E set(int index, E element) {if (index >= elementCount)throw new ArrayIndexOutOfBoundsException(index);E oldValue = elementData(index);elementData[index] = element;return oldValue;
}
包含
public boolean contains(Object o) {return indexOf(o, 0) >= 0;
}public synchronized int indexOf(Object o, int index) {if (o == null) {for (int i = index ; i < elementCount ; i++)if (elementData[i]==null)return i;} else {for (int i = index ; i < elementCount ; i++)if (o.equals(elementData[i]))return i;}return -1;
}
CopyOnWriteArrayList
是一個線程安全、并且在讀操作時無鎖的ArrayList。
很多時候,我們的系統應對的都是讀多寫少的并發場景。CopyOnWriteArrayList容器允許并發讀,讀操作是無鎖的,性能較高。至于寫操作,比如向容器中添加一個元素,則首先將當前容器復制一份,然后在新副本上執行寫操作,結束之后再將原容器的引用指向新容器。
?
優點
1)采用讀寫分離方式,讀的效率非常高
2)CopyOnWriteArrayList的迭代器是基于創建時的數據快照的,故數組的增刪改不會影響到迭代器
?
缺點
1)內存占用高,每次執行寫操作都要將原容器拷貝一份,數據量大時,對內存壓力較大,可能會引起頻繁GC
2)只能保證數據的最終一致性,不能保證數據的實時一致性。寫和讀分別作用在新老不同容器上,在寫操作執行過程中,讀不會阻塞但讀取到的卻是老容器的數據。
?
成員變量
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
構造方法
public CopyOnWriteArrayList() {setArray(new Object[0]);
}final void setArray(Object[] a) {array = a;
}
添加(有鎖,鎖內重新創建數組)
final Object[] getArray() {return array;}public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}
存在則添加(有鎖,鎖內重新創建數組)
先保存一份數組snapshot,如果snapshot中存在,則直接返回。
如果不存在,那么加鎖,獲取當前數組current,比較snapshot與current,遍歷它們共同長度內的元素,如果發現current中某一個元素等于e,那么直接返回(當然current與snapshot相同就不必看了);
之后再遍歷current單獨的部分,如果發現current中某一個元素等于e,那么直接返回;
此時可以去創建一個長度+1的新數組,將e加入。
public boolean addIfAbsent(E e) {Object[] snapshot = getArray();return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :addIfAbsent(e, snapshot);
}private boolean addIfAbsent(E e, Object[] snapshot) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] current = getArray();int len = current.length;if (snapshot != current) {// Optimize for lost race to another addXXX operationint common = Math.min(snapshot.length, len);for (int i = 0; i < common; i++)//如果snapshot與current元素不同但current與e相同,那么直接返回(掃描0到common)if (current[i] != snapshot[i] && eq(e, current[i]))return false;// 如果current中存在e,那么直接返回(掃描commen到len)if (indexOf(e, current, common, len) >= 0)return false;}Object[] newElements = Arrays.copyOf(current, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}
?
刪除(有鎖,鎖內重新創建數組)
public E remove(int index) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;E oldValue = get(elements, index);int numMoved = len - index - 1;if (numMoved == 0)setArray(Arrays.copyOf(elements, len - 1));else {Object[] newElements = new Object[len - 1];System.arraycopy(elements, 0, newElements, 0, index);System.arraycopy(elements, index + 1, newElements, index,numMoved);setArray(newElements);}return oldValue;} finally {lock.unlock();}
}
?
獲取(無鎖)
public E get(int index) {return get(getArray(), index);
}private E get(Object[] a, int index) {return (E) a[index];
}
更新(有鎖,鎖內重新創建數組)
public E set(int index, E element) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();E oldValue = get(elements, index);if (oldValue != element) {int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len);newElements[index] = element;setArray(newElements);} else {// 為了保持“volatile”的語義,任何一個讀操作都應該是一個寫操作的結果,也就是讀操作看到的數據一定是某個寫操作的結果(盡管寫操作沒有改變數據本身)。所以這里即使不設置也沒有問題,僅僅是為了一個語義上的補充(就如源碼中的注釋所言)// Not quite a no-op; ensures volatile write semanticssetArray(elements);}return oldValue;} finally {lock.unlock();}
}
包含(無鎖)
public boolean contains(Object o) {Object[] elements = getArray();return indexOf(o, elements, 0, elements.length) >= 0;
}private static int indexOf(Object o, Object[] elements,int index, int fence) {if (o == null) {for (int i = index; i < fence; i++)if (elements[i] == null)return i;} else {for (int i = index; i < fence; i++)if (o.equals(elements[i]))return i;}return -1;
}
List實現類之間的區別
(1) 對于需要快速插入,刪除元素,應該使用LinkedList。
(2) 對于需要快速隨機訪問元素,應該使用ArrayList。
(3) 對于“單線程環境” 或者 “多線程環境,但List僅僅只會被單個線程操作”,此時應該使用非同步的類(如ArrayList)。
?? 對于“多線程環境,且List可能同時被多個線程操作”,此時,應該使用同步的類(如Vector、CopyOnWriteArrayList)。
?