终于,我读懂了所有Java集合——List篇
?
ArrayList
基于數(shù)組實(shí)現(xiàn),無容量的限制。
在執(zhí)行插入元素時(shí)可能要擴(kuò)容,在刪除元素時(shí)并不會(huì)減小數(shù)組的容量,在查找元素時(shí)要遍歷數(shù)組,對(duì)于非null的元素采取equals的方式尋找。
是非線程安全的。
注意點(diǎn):
(1)ArrayList隨機(jī)存取元素時(shí)間復(fù)雜度O(1),插入刪除操作需大量移動(dòng)元素,效率較低
(2)為了節(jié)約內(nèi)存,當(dāng)新建容器為空時(shí),會(huì)共享
Object[] EMPTY_ELEMENTDATA = {}和
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}空數(shù)組
(3)容器底層采用數(shù)組存儲(chǔ),每次擴(kuò)容為1.5倍
(4)ArrayList的實(shí)現(xiàn)中大量地調(diào)用了Arrays.copyof()和System.arraycopy()方法,其實(shí)Arrays.copyof()內(nèi)部也是調(diào)用System.arraycopy()。System.arraycopy()為Native方法
(5)兩個(gè)ToArray方法
Object[] toArray()方法。該方法有可能會(huì)拋出java.lang.ClassCastException異常
<T> T[] toArray(T[] a)方法。該方法可以直接將ArrayList轉(zhuǎn)換得到的Array進(jìn)行整體向下轉(zhuǎn)型
(6)ArrayList可以存儲(chǔ)null值
(7)ArrayList每次修改(增加、刪除)容器時(shí),都是修改自身的modCount;在生成迭代器時(shí),迭代器會(huì)保存該modCount值,迭代器每次獲取元素時(shí),會(huì)比較自身的modCount與ArrayList的modCount是否相等,來判斷容器是否已經(jīng)被修改,如果被修改了則拋出異常(fast-fail機(jī)制)。
?
源碼解析
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;/*** 默認(rèn)容量*/private static final int DEFAULT_CAPACITY = 10;/*** 對(duì)象數(shù)組*/private static final Object[] EMPTY_ELEMENTDATA = {};/*** 默認(rèn)的空數(shù)組,無參構(gòu)造函數(shù)創(chuàng)建的數(shù)組*/private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};/*** 存放數(shù)據(jù)的數(shù)組的緩存變量*/transient Object[] elementData;/*** 元素?cái)?shù)量* */private int size;/*** 帶有容量的構(gòu)造方法* * @param 數(shù)組的初始容量* @throws IllegalArgumentException 參數(shù)為負(fù)*/public ArrayList(int initialCapacity) {// 參數(shù)>0if (initialCapacity > 0) {// new一個(gè)object數(shù)組賦給elementDatathis.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {// 參數(shù)=0// 將空數(shù)組賦給elementDatathis.elementData = EMPTY_ELEMENTDATA;} else {//參數(shù)<0,拋出IllegalArgumentException異常throw new IllegalArgumentException("Illegal Capacity: " +initialCapacity);}}/*** 不帶參數(shù)構(gòu)造方法*/public ArrayList() {// 將空數(shù)組賦給elementDatathis.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** 帶參數(shù)Collection的構(gòu)造方法* * @param c* 其元素將被放入此列表中的集合* @throws NullPointerException* 集合為空*/public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray可能(錯(cuò)誤地)不返回對(duì)象[](JAVA BUG編號(hào)6260652)if (elementData.getClass() != Object[].class)// Array.copyOf()主要用來將原數(shù)組拷貝到一個(gè)新的數(shù)組,適用于數(shù)組擴(kuò)容。elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// 空數(shù)組this.elementData = EMPTY_ELEMENTDATA;}}/*** 因?yàn)槿萘炕緯?huì)大于實(shí)際元素的數(shù)量。內(nèi)存緊張時(shí),可以調(diào)用該方法調(diào)整容量為元素實(shí)際數(shù)量。* 如果確定不會(huì)有元素添加進(jìn)來時(shí)也可以調(diào)用該方法來節(jié)約空間*/public void trimToSize() {modCount++;// 如果size小于lengthif (size < elementData.length) {// 將elementData設(shè)置大小為sizeelementData = (size == 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size);}}/*** 使用指定參數(shù)設(shè)置數(shù)組容量* * @param minCapacity* 所需的最小容量*/public void ensureCapacity(int minCapacity) {// 如果數(shù)組為空,容量預(yù)取0,否則去默認(rèn)值(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;// 若參數(shù)大于預(yù)設(shè)的容量,再使用該參數(shù)進(jìn)一步設(shè)置數(shù)組容量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;}/*** 得到最小擴(kuò)容量* * @param minCapacity*/private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}/*** 判斷是否需要擴(kuò)容* * @param minCapacity*/private void ensureExplicitCapacity(int minCapacity) {modCount++;// 最小需要空間比elementData的內(nèi)存空間大if (minCapacity - elementData.length > 0)grow(minCapacity);}/*** 數(shù)組的最大容量,可能會(huì)導(dǎo)致內(nèi)存溢出*/private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;/*** 擴(kuò)容* * @param minCapacity* 所需的最小容量*/private void grow(int minCapacity) {// ArrayList中elementData的內(nèi)存空間長度int oldCapacity = elementData.length;// 擴(kuò)容原來的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);// 判斷新數(shù)組的容量夠不夠// 不夠就將數(shù)組長度設(shè)置為需要的長度if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 預(yù)設(shè)值>默認(rèn)的最大值,檢查溢出if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 放到新數(shù)組中elementData = Arrays.copyOf(elementData, newCapacity);}/*** 檢查是否溢出,若沒有溢出,返回最大整數(shù)值或默認(rèn)最大值* * @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中的元素?cái)?shù)量*/public int size() {return size;}/*** 返回是否為空* * @return true 如果ArrayList中無元素*/public boolean isEmpty() {return size == 0;}/*** 是否包含一個(gè)數(shù) 返回bool* * @param o* 被檢查元素* @return true 如果ArrayList中包含o元素*/public boolean contains(Object o) {return indexOf(o) >= 0;}/*** 返回一個(gè)值首次出現(xiàn)的位置,不存在就返回-1。時(shí)間復(fù)雜度O(N)* * 返回第一個(gè)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;}/*** 返回一個(gè)值最后一次出現(xiàn)的位置,不存在就返回-1。時(shí)間復(fù)雜度O(N)* 返回最后一個(gè)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;}/*** 返回副本,元素本身沒有被復(fù)制,復(fù)制過程中數(shù)組發(fā)生改變會(huì)拋出異常* * @return v ArrayList副本*/public Object clone() {try {// 調(diào)用Object類的clone方法得到ArrayList副本ArrayList<?> v = (ArrayList<?>) super.clone();// 調(diào)用copyOf,將ArrayList的elementData數(shù)組賦給副本的elementData數(shù)組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);}}/*** 轉(zhuǎn)換為Object數(shù)組* * @return 一個(gè)數(shù)組包含所有列表中的元素*/public Object[] toArray() {return Arrays.copyOf(elementData, size);}/*** 將ArrayList里面的元素賦值到一個(gè)數(shù)組中去* a的長度小于ArrayList的長度,直接調(diào)用Arrays類的copyOf* a的長度大于ArrayList的長度,調(diào)用System.arraycopy,然后把size位置賦值為空。* * @param a* 如果它的長度大的話,列表元素存儲(chǔ)在這個(gè)數(shù)組中; 否則分配一個(gè)新數(shù)組。* @return 一個(gè)包含ArrayList元素的數(shù)組* @throws ArrayStoreException* 將與數(shù)組類型不兼容的值賦值給數(shù)組元素時(shí)拋出的異常* @throws NullPointerException* 數(shù)組為空*/@SuppressWarnings("unchecked")public <T> T[] toArray(T[] a) {if (a.length < size)// 創(chuàng)建一個(gè)新的a的運(yùn)行時(shí)類型數(shù)組,內(nèi)容不變r(jià)eturn (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];}/*** 返回指定位置的值,先檢查是否超出數(shù)組長度* * @param index* 元素的索引* @return ArrayList中指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E get(int index) {// 檢查是否越界rangeCheck(index);// 返回ArrayList的elementData數(shù)組index位置的元素return elementData(index);}/*** 設(shè)置指定位置為一個(gè)新值,返回之前的值* * @param index* 要替換的元素的索引* @param element* 要存儲(chǔ)在指定位置的元素* @return 之前在指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E set(int index, E element) {// 檢查越界rangeCheck(index);// 獲取當(dāng)前位置的值E oldValue = elementData(index);// 將element賦值到index位置elementData[index] = element;return oldValue;}/*** 添加一個(gè)值,首先會(huì)確保容量* * @param e* 要添加到此列表中的元素* @return <tt>true</tt> (as specified by {@link Collection#add})*/public boolean add(E e) {// 擴(kuò)容ensureCapacityInternal(size + 1);// 將e賦值給elementData的size+1的位置elementData[size++] = e;return true;}/*** index位置添加元素element,會(huì)檢查添加的位置和容量* * @param index* 指定元素將被插入的索引* @param element* 要插入的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public void add(int index, E element) {// 判斷越界rangeCheckForAdd(index);// 擴(kuò)容ensureCapacityInternal(size + 1); // Increments modCount!!// 將elementData從index位置開始,復(fù)制到elementData的index+1開始的連續(xù)空間System.arraycopy(elementData, index, elementData, index + 1,size - index);// 在index位置賦值elementelementData[index] = element;// ArrayList的大小++size++;}/*** 移除index位置的元素,會(huì)檢查去除的位置* * @param index* 要?jiǎng)h除的元素的索引* @return 刪除的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E remove(int index) {// 判斷越界rangeCheck(index);modCount++;// 讀取舊值E oldValue = elementData(index);// 獲取index位置開始到最后一個(gè)位置的個(gè)數(shù)int numMoved = size - index - 1;if (numMoved > 0)// index+1位置開始拷貝到從index開始的空間System.arraycopy(elementData, index + 1, elementData, index,numMoved);elementData[--size] = null; // 便于垃圾回收器回收return oldValue;}/*** 移除對(duì)象為O的元素,跟indexOf方法思想基本一致* @param o* 要從該列表中刪除的元素(如果存在)* @return true 如果這個(gè)列表包含指定的元素*/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; // 便于垃圾回收器回收}/*** 清空數(shù)組,把每一個(gè)值設(shè)為null,方便垃圾回收(不同于reset,數(shù)組默認(rèn)大小有改變的話不會(huì)重置)*/public void clear() {modCount++;// 便于垃圾回收器回收for (int i = 0; i < size; i++)elementData[i] = null;size = 0;}/*** 添加一個(gè)集合的元素到末端* * @param c* 包含要添加到此列表中的元素的集合* @return true 如果該列表因添加而改變* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(Collection<? extends E> c) {// c轉(zhuǎn)換為數(shù)組aObject[] a = c.toArray();// a占的內(nèi)存空間長度賦值給numNewint numNew = a.length;// 擴(kuò)容至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* 在哪個(gè)索引開始插入* @param c* 包含要添加到此列表中的元素的集合* @return true 如果該列表因添加而改變* @throws IndexOutOfBoundsException* {@inheritDoc}* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);// 將c轉(zhuǎn)換為數(shù)組aObject[] a = c.toArray();int numNew = a.length;// 擴(kuò)容至size + numNewensureCapacityInternal(size + numNew);// 獲取需要添加的個(gè)數(shù)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是否超出數(shù)組長度*/private void rangeCheck(int index) {// 如果下標(biāo)超過ArrayList的數(shù)組長度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);// 調(diào)用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);// 調(diào)用batchRemove保留c中的元素return batchRemove(c, true);}/*** 根據(jù)complement值,將ArrayList中包含c中元素的元素刪除或者保留* * @param c* @param complement* true時(shí)從數(shù)組保留指定集合中元素的值,為false時(shí)從數(shù)組刪除指定集合中元素的值。* @return 數(shù)組中重復(fù)的元素都會(huì)被刪除(而不是僅刪除一次或幾次),有任何刪除操作都會(huì)返回true*/private boolean batchRemove(Collection<?> c, boolean complement) {final Object[] elementData = this.elementData;// 定義一個(gè)w,一個(gè)r,兩個(gè)同時(shí)右移int r = 0, w = 0;boolean modified = false;try {// r先右移for (; r < size; r++)// 如果c中不包含elementData[r]這個(gè)元素if (c.contains(elementData[r]) == complement)// 則直接將r位置的元素賦值給w位置的元素,w自增elementData[w++] = elementData[r];} finally {// 防止拋出異常導(dǎo)致上面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;// 改變的次數(shù)// 新的大小為保留的元素的個(gè)數(shù)size = w;modified = true;}}return modified;}/*** 保存數(shù)組實(shí)例的狀態(tài)到一個(gè)流(即序列化)。寫入過程數(shù)組被更改會(huì)拋出異常* * @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;// 執(zhí)行默認(rèn)的反序列化/序列化過程。將當(dāng)前類的非靜態(tài)和非瞬態(tài)字段寫入此流s.defaultWriteObject();// 寫入大小s.writeInt(size);// 寫入所有元素for (int i = 0; i < size; i++) {s.writeObject(elementData[i]);}if (modCount != expectedModCount) {throw new ConcurrentModificationException();}}/*** 從流中重構(gòu)ArrayList實(shí)例(即反序列化)。*/private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {elementData = EMPTY_ELEMENTDATA;// 執(zhí)行默認(rèn)的序列化/反序列化過程s.defaultReadObject();// 讀入數(shù)組長度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();}}}/*** 返回一個(gè)從index開始的ListIterator對(duì)象* * @throws IndexOutOfBoundsException* {@inheritDoc}*/public ListIterator<E> listIterator(int index) {if (index < 0 || index > size)throw new IndexOutOfBoundsException("Index: " + index);return new ListItr(index);}/*** 返回一個(gè)ListIterator對(duì)象,ListItr為ArrayList的一個(gè)內(nèi)部類,實(shí)現(xiàn)了ListIterator<E> 接口* * @see #listIterator(int)*/public ListIterator<E> listIterator() {return new ListItr(0);}/*** 返回一個(gè)Iterator對(duì)象,Itr為ArrayList的一個(gè)內(nèi)部類,實(shí)現(xiàn)了Iterator<E>接口* * @return an iterator over the elements in this list in proper sequence*/public Iterator<E> iterator() {return new Itr();}/*** 通用的迭代器實(shí)現(xiàn)*/private class Itr implements Iterator<E> {int cursor; // 下一個(gè)元素的索引,默認(rèn)為0int lastRet = -1; // 上次訪問的元素的位置int expectedModCount = modCount;// 迭代過程修改數(shù)組拋出異常// 是否還有下一個(gè)public boolean hasNext() {return cursor != size;}// 下一個(gè)元素@SuppressWarnings("unchecked")public E next() {checkForComodification();// 檢查數(shù)組是否被修改int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;// 向后移動(dòng)游標(biāo)return (E) elementData[lastRet = i];// 設(shè)置訪問的位置并返回這個(gè)值}// 刪除元素public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();// 檢查數(shù)組是否被修改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();}// 檢查數(shù)組是否被修改final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}/*** ListIterator迭代器實(shí)現(xiàn)*/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的一個(gè)視圖,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 + ")");}/*** 子數(shù)組*/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();}};}/*** 返回指定范圍的子數(shù)組* * @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 使用流遍歷數(shù)組*/@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();}}/*** 為了并行遍歷元素而設(shè)計(jì)的一個(gè)迭代器* @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?接口的鏈接列表實(shí)現(xiàn)。實(shí)現(xiàn)所有可選的列表操作,并且允許所有元素(包括?null)。
除了實(shí)現(xiàn)?List?接口外,LinkedList?類還為在列表的開頭及結(jié)尾?get、remove?和?insert?元素提供了統(tǒng)一的命名方法。這些操作允許將鏈接列表用作堆棧、隊(duì)列或雙端隊(duì)列。
此類實(shí)現(xiàn)?Deque?接口,為?add、poll?提供先進(jìn)先出隊(duì)列操作,以及其他堆棧和雙端隊(duì)列操作。
所有操作都是按照雙重鏈接列表的需要執(zhí)行的。在列表中編索引的操作將從開頭或結(jié)尾遍歷列表(從靠近指定索引的一端)。
操作效率:大部分效率都是o(n)的
同步:
注意,此實(shí)現(xiàn)不是同步的。如果多個(gè)線程同時(shí)訪問一個(gè)鏈接列表,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了該列表,則它必須?保持外部同步。(結(jié)構(gòu)修改指添加或刪除一個(gè)或多個(gè)元素的任何操作;僅設(shè)置元素的值不是結(jié)構(gòu)修改。)這一般通過對(duì)自然封裝該列表的對(duì)象進(jìn)行同步操作來完成。如果不存在這樣的對(duì)象,則應(yīng)該使用?Collections.synchronizedList?方法來“包裝”該列表。最好在創(chuàng)建時(shí)完成這一操作,以防止對(duì)列表進(jìn)行意外的不同步訪問,如下所示:
List list = Collections.synchronizedList(new LinkedList(...));iterator :
此類的?iterator?和?listIterator?方法返回的迭代器是快速失敗?的:在迭代器創(chuàng)建之后,如果從結(jié)構(gòu)上對(duì)列表進(jìn)行修改,除非通過迭代器自身的?remove?或?add?方法,其他任何時(shí)間任何方式的修改,迭代器都將拋出?ConcurrentModificationException。因此,面對(duì)并發(fā)的修改,迭代器很快就會(huì)完全失敗,而不冒將來不確定的時(shí)間任意發(fā)生不確定行為的風(fēng)險(xiǎn)。
注意,迭代器的快速失敗行為不能得到保證,一般來說,存在不同步的并發(fā)修改時(shí),不可能作出任何硬性保證。快速失敗迭代器盡最大努力拋出?ConcurrentModificationException。因此,編寫依賴于此異常的程序的方式是錯(cuò)誤的,正確做法是:迭代器的快速失敗行為應(yīng)該僅用于檢測(cè)程序錯(cuò)誤。
源碼解析
package java.util; import java.util.function.Consumer; public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable {/*** 元素?cái)?shù)量*/transient int size = 0;/*** 首結(jié)點(diǎn)引用*/transient Node<E> first;/*** 尾節(jié)點(diǎn)引用*/transient Node<E> last;/*** 無參構(gòu)造方法*/public LinkedList() {}/*** 通過一個(gè)集合初始化,元素順序有這個(gè)集合的迭代器返回順序決定* * @param c* 其元素將被放入此列表中的集合* @throws NullPointerException* 如果指定的集合是空的*/public LinkedList(Collection<? extends E> c) {// 調(diào)用無參構(gòu)造this();// 添加所有的元素addAll(c);}/*** 頭插,內(nèi)部使用*/private void linkFirst(E e) {// 當(dāng)前首結(jié)點(diǎn)final Node<E> f = first;// 構(gòu)建新節(jié)點(diǎn)final Node<E> newNode = new Node<>(null, e, f);// 將newNode作為首節(jié)點(diǎn)first = newNode;// 如果原首節(jié)點(diǎn)為null,即原鏈表為null,則鏈表尾節(jié)點(diǎn)也設(shè)置為newNodeif (f == null)last = newNode;else // 否則,原首節(jié)點(diǎn)的prev設(shè)置為newNodef.prev = newNode;size++; // 長度+1modCount++; // 修改次數(shù)+1}/*** 尾插*/void linkLast(E e) {// 獲取尾結(jié)點(diǎn)final Node<E> l = last;// 構(gòu)建新節(jié)點(diǎn)final Node<E> newNode = new Node<>(l, e, null);// newNode作為尾節(jié)點(diǎn)last = newNode;// 如果原尾節(jié)點(diǎn)為null,即原鏈表為null,則鏈表首節(jié)點(diǎn)也設(shè)置為newNodeif (l == null)first = newNode;else // 否則,原尾節(jié)點(diǎn)的next設(shè)置為newNodel.next = newNode;size++;modCount++;}/*** 在非空節(jié)點(diǎn)succ前插入節(jié)點(diǎn)值e*/void linkBefore(E e, Node<E> succ) {final Node<E> pred = succ.prev;// 構(gòu)建新節(jié)點(diǎn)final Node<E> newNode = new Node<>(pred, e, succ);// 設(shè)置newNode為succ的前節(jié)點(diǎn)succ.prev = newNode;// 如果succ.prev為null,即succ為首節(jié)點(diǎn),則將newNode設(shè)置為首節(jié)點(diǎn)if (pred == null)first = newNode;else // 如果succ不是首節(jié)點(diǎn)pred.next = newNode;size++;modCount++;}/*** 刪除首結(jié)點(diǎn),返回存儲(chǔ)的元素,內(nèi)部使用*/private E unlinkFirst(Node<E> f) {// 獲取首結(jié)點(diǎn)存儲(chǔ)的元素final E element = f.item;// 獲取首結(jié)點(diǎn)的后繼結(jié)點(diǎn)final Node<E> next = f.next;// 刪除首結(jié)點(diǎn)f.item = null;f.next = null; // 便于垃圾回收// 首結(jié)點(diǎn)后繼結(jié)點(diǎn)設(shè)為首結(jié)點(diǎn)first = next;// 如果原來首結(jié)點(diǎn)的后繼結(jié)點(diǎn)為空,則尾結(jié)點(diǎn)設(shè)為null// 否則,原來首結(jié)點(diǎn)的后繼結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)設(shè)為nullif (next == null)last = null;elsenext.prev = null;size--;modCount++;// 返回原來首結(jié)點(diǎn)存儲(chǔ)的元素return element;}/*** 刪除尾結(jié)點(diǎn),返回存儲(chǔ)的元素,內(nèi)部使用*/private E unlinkLast(Node<E> l) {// 獲取尾結(jié)點(diǎn)存儲(chǔ)的元素final E element = l.item;// 獲取尾結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)final Node<E> prev = l.prev;// 刪除尾結(jié)點(diǎn)l.item = null;l.prev = null; // help GC// 原來尾結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)設(shè)為尾結(jié)點(diǎn)last = prev;// 如果原來尾結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)為空,則首結(jié)點(diǎn)設(shè)為null// 否則,原來尾結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)的后繼結(jié)點(diǎn)設(shè)為nullif (prev == null)first = null;elseprev.next = null;size--;modCount++;// 返回原來尾結(jié)點(diǎn)存儲(chǔ)的元素return element;}/*** 刪除指定非空結(jié)點(diǎn),返回存儲(chǔ)的元素*/E unlink(Node<E> x) {// 獲取指定非空結(jié)點(diǎn)存儲(chǔ)的元素final E element = x.item;// 獲取指定非空結(jié)點(diǎn)的后繼結(jié)點(diǎn)final Node<E> next = x.next;// 獲取指定非空結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)final Node<E> prev = x.prev;/*** 如果指定非空結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)為空,則指定非空結(jié)點(diǎn)的后繼結(jié)點(diǎn)設(shè)為首結(jié)點(diǎn) * 否則,指定非空結(jié)點(diǎn)的后繼結(jié)點(diǎn)設(shè)為指定非空結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)的后繼結(jié)點(diǎn),* 指定非空結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)設(shè)為null*/if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}/*** 如果指定非空結(jié)點(diǎn)的后繼結(jié)點(diǎn)為空,則指定非空結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)設(shè)為尾結(jié)點(diǎn) * 否則,指定非空結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)設(shè)為指定非空結(jié)點(diǎn)的后繼結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn),* 指定非空結(jié)點(diǎn)的后繼結(jié)點(diǎn)設(shè)為null*/if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}// 指定非空結(jié)點(diǎn)存儲(chǔ)的元素設(shè)為nullx.item = null;size--;modCount++;// 返回指定非空結(jié)點(diǎn)存儲(chǔ)的元素return element;}/*** 獲取首結(jié)點(diǎn)存儲(chǔ)的元素* * @return 首結(jié)點(diǎn)存儲(chǔ)的元素* @throws NoSuchElementException* 如果鏈表為空*/public E getFirst() {// 獲取首結(jié)點(diǎn)引用final Node<E> f = first;// 如果首結(jié)點(diǎn)為空,則拋出無該元素異常if (f == null)throw new NoSuchElementException();// 返回首結(jié)點(diǎn)存儲(chǔ)的元素return f.item;}/*** 獲取尾結(jié)點(diǎn)存儲(chǔ)的元素* * @return 尾結(jié)點(diǎn)存儲(chǔ)的元素* @throws NoSuchElementException* 如果鏈表為空*/public E getLast() {// 獲取尾結(jié)點(diǎn)引用final Node<E> l = last;// 如果尾結(jié)點(diǎn)為空,則拋出無該元素異常if (l == null)throw new NoSuchElementException();// 返回尾結(jié)點(diǎn)存儲(chǔ)的元素return l.item;}/*** 刪除首結(jié)點(diǎn),返回存儲(chǔ)的元素* * @return 首結(jié)點(diǎn)存儲(chǔ)的元素* @throws NoSuchElementException* 如果鏈表為空*/public E removeFirst() {// 獲取首結(jié)點(diǎn)引用final Node<E> f = first;// 如果首結(jié)點(diǎn)為空,則拋出無該元素異常if (f == null)throw new NoSuchElementException();// 刪除首結(jié)點(diǎn),返回存儲(chǔ)的元素return unlinkFirst(f);}/*** 刪除尾結(jié)點(diǎn),返回存儲(chǔ)的元素* * @return 尾結(jié)點(diǎn)存儲(chǔ)的元素* @throws NoSuchElementException* 如果鏈表為空*/public E removeLast() {// 獲取尾結(jié)點(diǎn)引用final Node<E> l = last;// 如果尾結(jié)點(diǎn)為空,則拋出無該元素異常if (l == null)throw new NoSuchElementException();// 刪除尾結(jié)點(diǎn),返回存儲(chǔ)的元素return unlinkLast(l);}/*** 頭部插入指定元素* * @param e* 要添加的元素*/public void addFirst(E e) {// 通過頭插法來插入指定元素linkFirst(e);}/*** 尾部插入指定元素,該方法等價(jià)于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;}/*** 獲取元素?cái)?shù)量* * @return 元素?cái)?shù)量*/public int size() {return size;}/*** 插入指定元素,返回操作結(jié)果,默認(rèn)添加到末尾作為最后一個(gè)元素* * @param e* 要添加到此鏈表中的元素* @return {@code true} (as specified by {@link Collection#add})*/public boolean add(E e) {// 通過尾插法來插入指定元素linkLast(e);return true;}/*** 刪除指定元素,默認(rèn)從first節(jié)點(diǎn)開始,刪除第一次出現(xiàn)的那個(gè)元素* * @param o* 要從該列表中刪除的元素(如果存在)* @return {@code true} 如果這個(gè)列表包含指定的元素*/public boolean remove(Object o) {// 會(huì)根據(jù)是否為null分開處理。若值不是null,會(huì)用到對(duì)象的equals()方法if (o == null) {// 遍歷鏈表,查找到指定元素后刪除該結(jié)點(diǎn),返回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* 在哪個(gè)索引處前插入指定集合中的第一個(gè)元素* @param c* 包含要添加到此鏈表中的元素的集合* @return {@code true} 如果該鏈表因添加而改變* @throws IndexOutOfBoundsException* {@inheritDoc}* @throws NullPointerException* 如果指定的集合是空的*/public boolean addAll(int index, Collection<? extends E> c) {// 檢查索引是否正確(0<=index<=size)checkPositionIndex(index);// 得到元素?cái)?shù)組Object[] a = c.toArray();// 得到元素個(gè)數(shù)int numNew = a.length;// 沒有元素,返回falseif (numNew == 0)return false;// succ指向當(dāng)前需要插入節(jié)點(diǎn)的位置,pred指向其前一個(gè)節(jié)點(diǎn)Node<E> pred, succ;// 末尾開始添加,當(dāng)前節(jié)點(diǎn)后一個(gè)節(jié)點(diǎn)為null,前一個(gè)節(jié)點(diǎn)為尾節(jié)點(diǎn)if (index == size) {succ = null;pred = last;} else { //當(dāng)前位置的節(jié)點(diǎn)為指定位置的節(jié)點(diǎn),前一個(gè)節(jié)點(diǎn)為要添加的節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)succ = node(index);pred = succ.prev;}// 遍歷數(shù)組并添加到列表中for (Object o : a) {@SuppressWarnings("unchecked") E e = (E) o;// “封裝”一個(gè)新節(jié)點(diǎn)Node<E> newNode = new Node<>(pred, e, null);// 原鏈表為null,新插入的節(jié)點(diǎn)作為鏈表首節(jié)點(diǎn)if (pred == null)first = newNode;elsepred.next = newNode; // 存在前節(jié)點(diǎn),前節(jié)點(diǎn)向后指向新加的節(jié)點(diǎn)pred = newNode; // pred指針向后移動(dòng)}// 從最后開始添加,則新節(jié)點(diǎn)成為尾節(jié)點(diǎn)if (succ == null) {last = pred;} else {pred.next = succ; // 新節(jié)點(diǎn)向后指向之前得到的后續(xù)第一個(gè)節(jié)點(diǎn)succ.prev = pred; // 后續(xù)的第一個(gè)節(jié)點(diǎn)也應(yīng)改為向前指向最后一個(gè)添加的節(jié)點(diǎn)}size += numNew;modCount++;return true;}/*** 刪除所有元素*/public void clear() {// 遍歷鏈表,刪除所有結(jié)點(diǎn),方便gc回收垃圾for (Node<E> x = first; x != null; ) {Node<E> next = x.next;x.item = null;x.next = null;x.prev = null;x = next;}// 首尾結(jié)點(diǎn)置空first = last = null;// 元素?cái)?shù)量置0size = 0;modCount++;}// 位置訪問操作/*** 獲取指定位置的元素* * @param index* 要返回的元素的索引* @return 該鏈表中指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E get(int index) {// 判斷指定位置是否合法checkElementIndex(index);// 返回指定位置的元素return node(index).item;}/*** 修改指定位置的元素,返回之前元素* * @param index* 要替換的元素的索引* @param element* 要存儲(chǔ)在指定位置的元素* @return 之前在指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E set(int index, E element) {// 判斷指定位置是否合法checkElementIndex(index);// 獲取指定位置的結(jié)點(diǎn)Node<E> x = node(index);// 獲取該結(jié)點(diǎn)存儲(chǔ)的元素E oldVal = x.item;// 修改該結(jié)點(diǎn)存儲(chǔ)的元素x.item = element;// 返回該結(jié)點(diǎn)存儲(chǔ)的之前的元素return oldVal;}/*** 在指定位置前插入指定元素* 頭插法* @param index* 指定元素將被插入的索引* @param element* 要插入的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public void add(int index, E element) {// 判斷指定位置是否合法checkPositionIndex(index);// 如果指定位置在尾部,則通過尾插法來插入指定元素if (index == size)linkLast(element);else // 如果指定位置不是尾部,則添加到指定位置前l(fā)inkBefore(element, node(index));}/*** 刪除指定位置的元素,返回之前元素* * @param index* 要?jiǎng)h除的元素的索引* @return 之前在指定位置的元素* @throws IndexOutOfBoundsException* {@inheritDoc}*/public E remove(int index) {// 判斷指定位置是否合法checkElementIndex(index);// 刪除指定位置的結(jié)點(diǎn),返回之前元素return unlink(node(index));}/*** 判斷指定位置是否合法*/private boolean isElementIndex(int index) {return index >= 0 && index < size;}/*** 判斷迭代器遍歷時(shí)或插入元素時(shí)指定位置是否合法*/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));}/*** 獲取指定下標(biāo)的結(jié)點(diǎn)*/Node<E> node(int index) {// 如果指定下標(biāo)<一半元素?cái)?shù)量,則從首結(jié)點(diǎn)開始遍歷// 否則,從尾結(jié)點(diǎn)開始遍歷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;}}// 查詢操作/*** 獲取首次出現(xiàn)指定元素的位置 -1表示不存在* 同樣是根據(jù)是否為null進(jìn)行區(qū)分* @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;}/*** 獲取逆序下首次出現(xiàn)指定元素的位置 -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;}// 隊(duì)列操作/*** 出隊(duì)(從前端),獲得第一個(gè)元素,不存在會(huì)返回null,不會(huì)刪除元素(節(jié)點(diǎn)) 獲取首元素* * @return the head of this list, or {@code null} 如果鏈表為空* @since 1.5*/public E peek() {final Node<E> f = first;// 如果首結(jié)點(diǎn)為空,則返回null// 否則,返回首結(jié)點(diǎn)存儲(chǔ)的元素return (f == null) ? null : f.item;}/*** 出隊(duì)(從前端),不刪除元素,若為null會(huì)拋出異常而不是返回null 獲取首元素* * @return the head of this list* @throws NoSuchElementException* 如果鏈表為空* @since 1.5*/public E element() {// 返回首結(jié)點(diǎn)存儲(chǔ)的元素return getFirst();}/*** 出隊(duì)(從前端),如果不存在會(huì)返回null,存在的話會(huì)返回值并移除這個(gè)元素(節(jié)點(diǎn)) 獲取并刪除首元素* * @return the head of this list, or {@code null} 如果鏈表為空* @since 1.5*/public E poll() {// 獲取首結(jié)點(diǎn)引用final Node<E> f = first;// 如果首結(jié)點(diǎn)為空,則返回null// 否則,刪除首結(jié)點(diǎn),返回首結(jié)點(diǎn)存儲(chǔ)的元素return (f == null) ? null : unlinkFirst(f);}/*** 出隊(duì)(從前端),如果不存在會(huì)拋出異常而不是返回null,存在的話會(huì)返回值并移除這個(gè)元素(節(jié)點(diǎn)) 獲取并刪除首元素* * @return the head of this list* @throws NoSuchElementException* 如果鏈表為空* @since 1.5*/public E remove() {// 刪除首結(jié)點(diǎn),返回首結(jié)點(diǎn)存儲(chǔ)的元素return removeFirst();}/*** 入隊(duì)(從后端),始終返回true* * 鏈表不會(huì)溢出* @param e* the element to add* @return {@code true} (as specified by {@link Queue#offer})* @since 1.5*/public boolean offer(E e) {// 通過尾插法插入指定元素,返回操作結(jié)果return add(e);}// 雙端隊(duì)列操作/*** 入隊(duì)(從前端),始終返回true* * @param e* 要插入的元素* @return {@code true} (as specified by {@link Deque#offerFirst})* @since 1.6*/public boolean offerFirst(E e) {// 通過頭插法來插入指定元素addFirst(e);return true;}/*** 入隊(duì)(從后端),始終返回true* * @param e* 要插入的元素* @return {@code true} (as specified by {@link Deque#offerLast})* @since 1.6*/public boolean offerLast(E e) {// 通過尾插法來插入指定元素addLast(e);return true;}/*** 出隊(duì)(從前端),獲得第一個(gè)元素,不存在會(huì)返回null,不會(huì)刪除元素(節(jié)點(diǎn))* * @return the first element of this list, or {@code null} 如果鏈表為空* @since 1.6*/public E peekFirst() {// 獲取首結(jié)點(diǎn)引用final Node<E> f = first;// 如果首結(jié)點(diǎn)為空,則返回null// 否則,返回首結(jié)點(diǎn)存儲(chǔ)的元素return (f == null) ? null : f.item;}/*** 出隊(duì)(從后端),獲得最后一個(gè)元素,不存在會(huì)返回null,不會(huì)刪除元素(節(jié)點(diǎn))* * @return the last element of this list, or {@code null} 如果鏈表為空* @since 1.6*/public E peekLast() {// 獲取尾結(jié)點(diǎn)引用final Node<E> l = last;// 如果尾結(jié)點(diǎn)為空,則返回null// 否則,返回尾結(jié)點(diǎn)存儲(chǔ)的元素return (l == null) ? null : l.item;}/*** 出隊(duì)(從前端),獲得第一個(gè)元素,不存在會(huì)返回null,會(huì)刪除元素(節(jié)點(diǎn))* * @return the first element of this list, or {@code null} if this list is* empty* @since 1.6*/public E pollFirst() {// 獲取首結(jié)點(diǎn)引用final Node<E> f = first;// 如果首結(jié)點(diǎn)為空,則返回null// 否則,刪除首結(jié)點(diǎn),返回首結(jié)點(diǎn)存儲(chǔ)的元素return (f == null) ? null : unlinkFirst(f);}/*** 出隊(duì)(從后端),獲得最后一個(gè)元素,不存在會(huì)返回null,會(huì)刪除元素(節(jié)點(diǎn))* * @return the last element of this list, or {@code null} if this list is* empty* @since 1.6*/public E pollLast() {// 獲取尾結(jié)點(diǎn)引用final Node<E> l = last;// 如果尾結(jié)點(diǎn)為空,則返回null// 否則,刪除尾結(jié)點(diǎn),返回尾結(jié)點(diǎn)存儲(chǔ)的元素return (l == null) ? null : unlinkLast(l);}/*** 入棧,從前面添加* * @param e* the element to push* @since 1.6*/public void push(E e) {// 通過頭插法來插入指定元素addFirst(e);}/*** 出棧,返回棧頂元素,從前面移除(會(huì)刪除)* * @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() {// 刪除首結(jié)點(diǎn),返回首結(jié)點(diǎn)存儲(chǔ)的元素return removeFirst();}/*** 刪除順序下首次出現(xiàn)的指定元素,返回操作結(jié)果* * @param o* 要從該列表中刪除的元素(如果存在)* @return {@code true} 如果鏈表包含指定的元素* @since 1.6*/public boolean removeFirstOccurrence(Object o) {// 刪除順序下首次出現(xiàn)的指定元素對(duì)應(yīng)的結(jié)點(diǎn),返回操作結(jié)果return remove(o);}/*** 刪除逆序下首次出現(xiàn)的指定元素,返回操作結(jié)果* * @param o* 要從該列表中刪除的元素(如果存在)* @return {@code true} 如果鏈表包含指定的元素* @since 1.6*/public boolean removeLastOccurrence(Object o) {// 由于LinkedList中允許存放null,因此下面通過兩種情況來分別處理if (o == null) {// 遍歷鏈表,從尾結(jié)點(diǎn)開始查找指定元素// 如果查找成功,刪除該結(jié)點(diǎn),返回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();}}/*** 節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu),包含前后節(jié)點(diǎn)的引用和當(dāng)前節(jié)點(diǎn)* * @param <E>*/private static class Node<E> {// 存儲(chǔ)的元素E item;// 后繼結(jié)點(diǎn)Node<E> next;// 前驅(qū)結(jié)點(diǎn)Node<E> prev;// 前驅(qū)結(jié)點(diǎn)、存儲(chǔ)的元素和后繼結(jié)點(diǎn)作為參數(shù)的構(gòu)造方法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();}/*** 因?yàn)椴捎面湵韺?shí)現(xiàn),所以迭代器很簡(jiǎn)單*/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);}}/*** 克隆,淺拷貝* * 淺拷貝時(shí),若存儲(chǔ)的是對(duì)象的引用,拷貝時(shí),對(duì)象本身的改變將表現(xiàn)到副本中,而深拷貝不會(huì)。* @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;// 插入結(jié)點(diǎn)for (Node<E> x = first; x != null; x = x.next)clone.add(x.item);// 返回克隆后的對(duì)象引用return clone;}/*** 返回新的數(shù)組,數(shù)組含有列表中所有元素*/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 {// 默認(rèn)序列化s.defaultWriteObject();// 寫入元素?cái)?shù)量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 {// 默認(rèn)反序列化s.defaultReadObject();// 讀取元素?cái)?shù)量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實(shí)現(xiàn)的線程安全的ArrayList,但在插入元素時(shí)容量擴(kuò)充的機(jī)制和ArrayList稍有不同,并可通過傳入capacityIncrement來控制容量的擴(kuò)充。
成員變量
protected Object[] elementData; protected int elementCount; protected int capacityIncrement;構(gòu)造方法
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; }擴(kuò)容
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
是一個(gè)線程安全、并且在讀操作時(shí)無鎖的ArrayList。
很多時(shí)候,我們的系統(tǒng)應(yīng)對(duì)的都是讀多寫少的并發(fā)場(chǎng)景。CopyOnWriteArrayList容器允許并發(fā)讀,讀操作是無鎖的,性能較高。至于寫操作,比如向容器中添加一個(gè)元素,則首先將當(dāng)前容器復(fù)制一份,然后在新副本上執(zhí)行寫操作,結(jié)束之后再將原容器的引用指向新容器。
?
優(yōu)點(diǎn)
1)采用讀寫分離方式,讀的效率非常高
2)CopyOnWriteArrayList的迭代器是基于創(chuàng)建時(shí)的數(shù)據(jù)快照的,故數(shù)組的增刪改不會(huì)影響到迭代器
?
缺點(diǎn)
1)內(nèi)存占用高,每次執(zhí)行寫操作都要將原容器拷貝一份,數(shù)據(jù)量大時(shí),對(duì)內(nèi)存壓力較大,可能會(huì)引起頻繁GC
2)只能保證數(shù)據(jù)的最終一致性,不能保證數(shù)據(jù)的實(shí)時(shí)一致性。寫和讀分別作用在新老不同容器上,在寫操作執(zhí)行過程中,讀不會(huì)阻塞但讀取到的卻是老容器的數(shù)據(jù)。
?
成員變量
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
構(gòu)造方法
public CopyOnWriteArrayList() {setArray(new Object[0]); }final void setArray(Object[] a) {array = a; }添加(有鎖,鎖內(nèi)重新創(chuàng)建數(shù)組)
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();} }存在則添加(有鎖,鎖內(nèi)重新創(chuàng)建數(shù)組)
先保存一份數(shù)組snapshot,如果snapshot中存在,則直接返回。
如果不存在,那么加鎖,獲取當(dāng)前數(shù)組current,比較snapshot與current,遍歷它們共同長度內(nèi)的元素,如果發(fā)現(xiàn)current中某一個(gè)元素等于e,那么直接返回(當(dāng)然current與snapshot相同就不必看了);
之后再遍歷current單獨(dú)的部分,如果發(fā)現(xiàn)current中某一個(gè)元素等于e,那么直接返回;
此時(shí)可以去創(chuàng)建一個(gè)長度+1的新數(shù)組,將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();} }?
刪除(有鎖,鎖內(nèi)重新創(chuàng)建數(shù)組)
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]; }更新(有鎖,鎖內(nèi)重新創(chuàng)建數(shù)組)
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”的語義,任何一個(gè)讀操作都應(yīng)該是一個(gè)寫操作的結(jié)果,也就是讀操作看到的數(shù)據(jù)一定是某個(gè)寫操作的結(jié)果(盡管寫操作沒有改變數(shù)據(jù)本身)。所以這里即使不設(shè)置也沒有問題,僅僅是為了一個(gè)語義上的補(bǔ)充(就如源碼中的注釋所言)// 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實(shí)現(xiàn)類之間的區(qū)別
(1) 對(duì)于需要快速插入,刪除元素,應(yīng)該使用LinkedList。
(2) 對(duì)于需要快速隨機(jī)訪問元素,應(yīng)該使用ArrayList。
(3) 對(duì)于“單線程環(huán)境” 或者 “多線程環(huán)境,但List僅僅只會(huì)被單個(gè)線程操作”,此時(shí)應(yīng)該使用非同步的類(如ArrayList)。
?? 對(duì)于“多線程環(huán)境,且List可能同時(shí)被多個(gè)線程操作”,此時(shí),應(yīng)該使用同步的類(如Vector、CopyOnWriteArrayList)。
?
總結(jié)
以上是生活随笔為你收集整理的终于,我读懂了所有Java集合——List篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 17校招真题题集(3)11-15
- 下一篇: 阿里Java编程规约(注释)提炼