LinkedList源碼解析

LinkedList 是List的一個實現類,並實現了Deque、Cloneable、Serializable 接口

實現 Deque 表示 LinkList 是一個雙向隊列

實現 Cloneable 表示LinkedList 可以被克隆

實現 Serializable 表示LinkedList 可以被序列化

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() {
}

// 集合構造
public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

        LinkedList 有兩種構造函數,如上所示。無參構造函數不需要過多解釋,就是創建一個空集合。集合構造函數就是把該Collection集合轉化爲一個LinkedList 並返回。

二、add 函數

        我們先從具體的函數實現來看以下 這到底是不是雙向鏈表的結構(雖然全局變量有 first last ),及如何把新的元素添加到雙向鏈表上面的。

public boolean add(E e) {
    linkLast(e);
    return true;
}

        可以看出,在新添加元素時,默認添加到尾部,進入linkLast 方法 看具體的實現:

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++;
}

        當添加第一個元素的時候,last first 皆爲 null ,因爲在添加元素前,該集合爲空。所以在第一次添加元素的時候 上述代碼第二行 l 爲null,那麼可以繼續看下Node 對應的構造函數:

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;
    }
}

        由於 當前只添加了一個元素,所以 Node 對應的 前一個元素的指向prev 及 後一個元素的指向 next 皆爲null。由於默認爲向集合尾部添加,所以新創建的Node節點指向last,由於第一次添加,所以 l == null ,在 linkLast 函數中第六行 該元素又被指向last。每次添加一個新元素時候 size自增1,代表整個集合中元素的個數。此時 集合中只有一個元素,該元素的前一個元素指向自身,後一個元素也是指向自身。

        接下來繼續添加第二個元素,爲了方便觀察,先把 linkLast 函數複製過來:

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++;
}

        此時第一個元素賦值給 l ,並創建一個新的Node節點,此Node節點的prev 指向之前添加的元素。並把新創建的Node節點賦給last , 把 l 的下一個節點指向 新創建的節點( l.next = newNode )。此時集合中有兩個元素,基本就能確定該集合具體是什麼結構的集合,可以回顧下,第二次添加的元素 在創建新的Node節點時,新節點的 prev 指向第一個節點,而 第一個節點的next 指向新創建的節點,用圖表示如下所示:

        通過上圖我們應該可以更好的理解 LinkedList 的結構 及 什麼樣的結構是雙向鏈表。當添加新的元素時,無論是 linkLast(向後添加),還是 linkBefore(前面插入),需要做的只是改變 元素 prev 和 next 的指向。由此我們也能得出一個結論 那就是LinkedList 的數據結構 插入與刪除的效率是非常高的(畢竟只是改變指向)。

        其他的函數 如 addAll  removeLast 等函數在此就不再 細看,原理相通,此文只是讓我們更好的理解LinkedList 的數據結構 及 什麼樣的結構是雙向鏈表。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章