1. 程式人生 > >Java集合原始碼分析之LikedList

Java集合原始碼分析之LikedList

一、LinkedList結構

 

  LinkedList是一種可以在任何位置進行高效地插入和移除操作的有序序列,它是基於雙向連結串列實現的。
  LinkedList 是一個繼承於AbstractSequentialList的雙向連結串列。它也可以被當作堆疊、佇列或雙端佇列進行操作。
  LinkedList 實現 List 介面,能對它進行佇列操作。
  LinkedList 實現 Deque 介面,即能將LinkedList當作雙端佇列使用。
  LinkedList 實現了Cloneable介面,即覆蓋了函式clone(),能克隆。
  LinkedList 實現java.io.Serializable介面,這意味著LinkedList支援序列化,能通過序列化去傳輸。
  LinkedList 是非同步的。

二、原始碼說明

  1.LikedList屬性

    //LinkedList的屬性非常簡單,一個頭結點、一個尾結點、一個表示連結串列中實際元素個數的變數。
    //注意,頭結點、尾結點都有transient關鍵字修飾,這也意味著在序列化時該域是不會序列化的。
    //元素個數    
    transient int size = 0;
    //頭結點
    transient Node<E> first;
    //尾節點    
    transient Node<E> last;

  2.建構函式

    public LinkedList() {
    
    }
    
public LinkedList(Collection<? extends E> c) { this(); addAll(c); }

  LinkedList沒有長度的概念,所以不存在容量不足的問題,因此不需要提供初始化大小的構造方法,因此只提供了兩個方法,一個是無參構造方法,初始一個LinkedList物件,一個是將指定的集合元素轉化為LinkedList構造方法。

  3.新增方法 add()

    public boolean add(E e) {
     linkLast(e);
     return true
; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }

  新增方法預設是新增到LinkedList的尾部,首先將last指定的節點賦值給l節點,然後新建節點newNode ,此節點的前驅指向l節點,data = e , next = null , 並將新節點賦值給last節點,它成為了最後一個節點,根據當前List是否為空做出相應的操作。若不為空將l的後繼指標修改為newNodw。 size +1 , modCount+1

   4.刪除方法

    public boolean remove(Object o) {
        if (o == null) {
            for (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;
    }

  刪除方法,先迴圈遍歷列表,找到item == o 的節點,在呼叫unlink()方法刪除

  5.查詢 get(index)

    //獲取指定位置的元素
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
    //返回指定位置的節點資訊,
    //LikedList無法隨機訪問,只能通過遍歷的方式找到相應的結點
    //為了提高效率,當前位置首先和元素的中間位置開始判斷,小於中間位置
    //從頭結點開始遍歷,大於中間位置從尾結點開始遍歷
    Node<E> node(int index) {
        // assert isElementIndex(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;
        }
    }

三、內部類介紹

  在LinkedList中除了有一個Node的內部類外,應該還能看到另外兩個內部類,那就是ListItr,還有一個是DescendingIterator。

  1.ListItr內部類

  

   

  •     看到方法名之後,就發現不止有向後迭代的方法,還有向前迭代的方法,所以我們就知道了這個ListItr這個內部類幹嘛用的了,就是能讓linkedList不光能像後迭代,也能向前迭代。
  •     看一下ListItr中的方法,可以發現,在迭代的過程中,還能移除、修改、新增值得操作。

   2.DescendingIterator內部類

    //看一下這個類,還是呼叫的ListItr,作用是封裝一下Itr中幾個方法,讓使用者以正常的思維去寫程式碼,例如,在從後往前遍歷的時候,
   //也是跟從前往後遍歷一樣,使用next等操作,而不用使用特殊的previous。
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(); } }

四、總結

  1. LinkedList是一個功能很強大的類,可以被當作List集合,雙端佇列和棧來使用。linkedList本質上是一個雙向連結串列,通過一個Node內部類實現的這種連結串列結構。
  2. 能儲存null值,在查詢和刪除某元素時,原始碼中都劃分為該元素為null和不為null兩種情況來處理,LinkedList中允許元素為null。
  3. 在實現的介面中,應該注意到沒有RandomAccess:那麼就推薦使用iterator,在其中就有一個foreach,增強的for迴圈,其中原理也就是iterator,我們在使用的時候,使用foreach或者iterator都可以。
  4. LikedList是順序存取結構(注意和隨機存取結構兩個概念搞清楚)
  5. LinkedList在1.8版本有添加了一點新的內容,添加了一個static final 修飾的內部類LLSpliterator 並實現了Spliterator ,
  6. LinkedList底層使用連結串列來儲存集合中的元素,因此隨機訪問的效能較差,但是插入刪除時效能非常的出色。

 

 

參考

   https://www.cnblogs.com/zhangyinhua/p/7688304.html

      https://my.oschina.net/90888/blog/1625505