LinkedList 學習筆記

先擺上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機制線程

相關文章
相關標籤/搜索