java8 LinkedList源碼分析

LinkedList特點:

數據結構用雙向鏈表實現,增刪元素性能較好。

實現了所有List的接口。

可以插入null元素。

不是線程安全的。

類定義

繼承AbstractSequentialList實現了List,Deque,Cloneable,Serializable接口。

    public class LinkedList<E>
            extends AbstractSequentialList<E>
            implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {
        //元素個數
        transient int size = 0;

        //頭結點
        transient java.util.LinkedList.Node<E> first;

        //尾結點
        transient java.util.LinkedList.Node<E> last;

構造函數

可以看出new LinkedList() 啥也沒幹。不會有額外的內存分配。

    /**
     * 創建一個空的list
     */
    public LinkedList() {
    }

    /**
     * 給定集合創建list
     */
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        //檢查index範圍是否合法
        checkPositionIndex(index);
        //轉換成數組
        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)//空的就不繼續執行
            return false;

        LinkedList.Node<E> pred, succ;
        if (index == size) {
            succ = null;
            pred = last;
        } else {
            succ = node(index);
            pred = succ.prev;
        }
        //遍歷集合轉換成數組的元素 逐一添加到鏈表裏面
        for (Object o : a) {
            @SuppressWarnings("unchecked") E e = (E) o;
            LinkedList.Node<E> newNode = new LinkedList.Node<>(pred, e, null);
            if (pred == null) //沒有第一個節點
                first = newNode;
            else //上一個節點的next指向修改成newNode
                pred.next = newNode;
            pred = newNode;
        }

        if (succ == null) {
            last = pred;
        } else {
            pred.next = succ;
            succ.prev = pred;
        }
        //修改元素大小
        size += numNew;
        modCount++;
        return true;
    }

add操作

add操作思路很簡單就是往鏈表的最後位置追加節點。

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

    /**
     * 插入到鏈表最後的位置
     */
    void linkLast(E e) {
        final LinkedList.Node<E> l = last;
        final LinkedList.Node<E> newNode = new LinkedList.Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

​

offer操作

其實就是add操作

public boolean offer(E e) {
        return add(e);
    }

 

get操作

get操作充分利用了雙向鏈表的特效,根據index與size的一半作比較,小於的話 從前往後找,大於等於就從後往前找。

 //獲取元素
    public E get(int index) {
        //檢查index是否有效
        checkElementIndex(index);
        return node(index).item;
    }

    /**
     * 獲取節點
     * @param index
     * @return
     */
    LinkedList.Node<E> node(int index) {
        // assert isElementIndex(index);
        //如果index小於size的一般從頭部開始找
        if (index < (size >> 1)) {
            LinkedList.Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {//index >= size的一般從尾部開始找
            LinkedList.Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

remove操作

就是雙向鏈表的刪除操作,修改要刪除節點的prev節點的next 和 刪除節點的next節點的prev節點即可。

public E remove(int index) {
        //檢查index
        checkElementIndex(index);
        //移除index的節點
        return unlink(node(index));
    }

 
    E unlink(LinkedList.Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final LinkedList.Node<E> next = x.next;
        final LinkedList.Node<E> prev = x.prev;
        //沒有前置節點,說明要刪除的節點是頭結點
        if (prev == null) {
            first = next;//修改頭結點爲刪除節點的next引用節點
        } else {//刪除節點的前節點指向刪除節點的next節點
            prev.next = next;
            x.prev = null;
        }
        //沒有netx說明是尾結點
        if (next == null) {
            last = prev;//修改尾結點的引用即可
        } else {//刪除節點的next節點指向刪除節點的prev節點
            next.prev = prev;
            x.next = null;
        }
        //刪除節點置null 
        x.item = null;
        size--;
        modCount++;
        return element;
    }

 

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