先擺上JDK1.8中hashMap的類註釋;我翻譯了一下java
/** * Doubly-linked list implementation of the {@code List} and {@code Deque} * interfaces. Implements all optional list operations, and permits all * elements (including {@code null}). * 雙向鏈表實現了List和Deque接口。實現了List全部的操做,雙向鏈表容許全部元素,包括null * * <p>All of the operations perform as could be expected for a doubly-linked * list. Operations that index into the list will traverse the list from * the beginning or the end, whichever is closer to the specified index. * 對於LinkedList全部的操做都是能夠被預期的。操做LinkedList將會遍歷LinkedList的指針. * 解讀:經過set(i,e),get(i)訪問LinkedList的元素時,要遍歷指針,若是i>LinkedList容量的一半, * 就從尾部開始遍歷. * * <p><strong>Note that this implementation is not synchronized.</strong> * If multiple threads access a linked list concurrently, and at least * one of the threads modifies the list structurally, it <i>must</i> be * synchronized externally. (A structural modification is any operation * that adds or deletes one or more elements; merely setting the value of * an element is not a structural modification.) This is typically * accomplished by synchronizing on some object that naturally * encapsulates the list. * 注意,LinkedList是線程不一樣步的.若是多線程同時訪問LinkedList,此時若是有一個線程修改LinkedList結構, * 那麼就必須在外層進行同步操做處理(這裏的修改結構包括添加元素,刪除元素)。 * 解讀:ArrayList一樣有此特性. * * If no such object exists, the list should be "wrapped" using the * {@link Collections#synchronizedList Collections.synchronizedList} * method. This is best done at creation time, to prevent accidental * unsynchronized access to the list:<pre> * List list = Collections.synchronizedList(new LinkedList(...));</pre> * 考慮線程同步問題,能夠用Collections.synchronizedList替代LindedList * * <p>The iterators returned by this class's {@code iterator} and * {@code listIterator} methods are <i>fail-fast</i>: if the list is * structurally modified at any time after the iterator is created, in * any way except through the Iterator's own {@code remove} or * {@code add} methods, the iterator will throw a {@link * 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. * 在迭代一個LinkedList時,任何修改LinkedList的操做,迭代器都會終止,並拋出 * ConcurrentModificationException異常. * * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators * throw {@code ConcurrentModificationException} on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this * exception for its correctness: <i>the fail-fast behavior of iterators * should be used only to detect bugs.</i> * 快速失敗機制,是一種錯誤檢測機制。它只能被用來檢測錯誤,由於JDK並不保證fail-fast機制必定會發生. * 參考個人博客 」Iterator fail-fast「 * * @author Josh Bloch * @see List * @see ArrayList * @since 1.2 * @param <E> the type of elements held in this collection */ public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
總結node
1. LinkedList是基於鏈表結構實現,因此在類中包含了first和last兩個指針(Node)。Node中包含了上一個節點和下一個節點的引用,這樣就構成了雙向的鏈表。每一個Node只能 數據結構
知道本身的前一個節點和後一個節點,但對於鏈表來講,這已經足夠了多線程
在此看一下LinkedList的數據結構,立體感覺一下這個特性app
因此LinkedList插入和刪除元素效率很高,比ArrayList高。經過set(i,e),get(i)訪問效率低,由於要遍歷指針,若是i>size/2,那麼就從尾部開始遍歷。ide
翻閱get(i),set(i,E)的源碼ui
1 /** 2 * Replaces the element at the specified position in this list with the 3 * specified element. 4 * 5 * @param index index of the element to replace 6 * @param element element to be stored at the specified position 7 * @return the element previously at the specified position 8 * @throws IndexOutOfBoundsException {@inheritDoc} 9 */ 10 public E set(int index, E element) { 11 checkElementIndex(index); 12 Node<E> x = node(index); 13 E oldVal = x.item; 14 x.item = element; 15 return oldVal; 16 } 17 18 /** 19 * Returns the element at the specified position in this list. 20 * 21 * @param index index of the element to return 22 * @return the element at the specified position in this list 23 * @throws IndexOutOfBoundsException {@inheritDoc} 24 */ 25 public E get(int index) { 26 checkElementIndex(index); 27 return node(index).item; 28 } 29 30 /** 31 * Returns the (non-null) Node at the specified element index. 32 */ 33 Node<E> node(int index) { 34 // assert isElementIndex(index); 35 36 if (index < (size >> 1)) { 37 Node<E> x = first; 38 for (int i = 0; i < index; i++) 39 x = x.next; 40 return x; 41 } else { 42 Node<E> x = last; 43 for (int i = size - 1; i > index; i--) 44 x = x.prev; 45 return x; 46 } 47 }
很明顯,在進行set和get操做時,並非每次都從頭部開始遍歷指針的,而是調用了node(int index)這個方法,就是用來判斷當前index的大體位置,若是i<(size>>1)也就是i<size/2,那麼從first開始遍歷,不然從last開始遍歷。此時set,get操做的時間複雜度也就由O(n)變成了O(n/2)this
2. 鏈表沒有容量限制,可是雙向鏈表自己使用了更多的空間.每插入一個元素都要構造一個Node對象spa
3. LinkedList線程不一樣步,採用fail-fast機制線程