1. 程式人生 > >JDK之LinkedList原始碼解讀(一)

JDK之LinkedList原始碼解讀(一)

目錄

建構函式

linkFirst(E e)

linkLast(E e)

linkBefore(E e, Node succ)


 

LinkedList由一系列Node節點組成,每一個節點指向前一個節點和後一個節點的引用,因此是一個雙向連結串列。

建構函式

一個是無參的建構函式,一個引數是Collection c的建構函式。第二個建構函式呼叫addAll(c)方法。

size是LinkedList的元素個數。

public boolean addAll(int index, Collection<? extends E> c) {
        checkPositionIndex(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;

        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;
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            pred = newNode;
        }

        if (succ == null) {
            last = pred;
        } else {
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;
        return true;
    }

先校驗index的正確性 checkPositionIndex(index)

private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }

如果index小於0或者大於LinkedList的長度,則丟擲越界異常。

 

linkFirst(E e)

 private void linkFirst(E e) {
        //將頭結點賦值給臨時變數f
        final Node<E> f = first;

        //建立一個新節點,它的前任節點為null,節點資料是傳入的引數E e, 後續節點就是原來的頭結點。這樣一來,這個節點就變成了新的頭結點
        final Node<E> newNode = new Node<>(null, e, f);

        //first再重新指向新的頭結點
        first = newNode;

        //假如原先的頭結點為null,說明原LinkedList是空的,那麼last也指向這個新節點,因為這時候只有一個節點,所以該節點既是頭結點,也是尾節點
        if (f == null)
            last = newNode;
        else        
            f.prev = newNode;
        //LinkedList長度加1
        size++;
        modCount++;
    }

作用:將新物件插入到LinkedList的頭部,作為新的頭結點。

linkLast(E e)

void linkLast(E e) {
        //將尾節點賦值給臨時變數l
        final Node<E> l = last;

        //建立一個新節點,它的前任節點是原來的尾結點,節點資料是傳入的引數E e, 後續節點為null。這樣一來,這個節點就變成了新的頭結點
        final Node<E> newNode = new Node<>(l, e, null);

        //last再重新指向新的尾結點
        last = newNode;

        //假如原先的尾結點為null,說明原LinkedList是空的,那麼first也指向這個新節點,因為這時候只有一個節點,所以該節點既是頭結點,也是尾節點
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        //LinkedList長度加1
        size++;
        modCount++;
    }

作用:將新物件插入到LinkedList的尾部,作為新的尾結點。

linkBefore(E e, Node<E> succ)

void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;

        //建立一個新節點,它的前任節點是指定節點succ的前任節點,節點資料是傳入的引數E e, 後續節點是該指定節點succ。這樣一來,這個節點就插入到該節點succ的前面了
        final Node<E> newNode = new Node<>(pred, e, succ);

        //該節點succ前任節點變成了剛才插入的新節點了
        succ.prev = newNode;

        //假如原先的尾結點為null,說明原LinkedList是空的,那麼first也指向這個新節點,因為這時候只有一個節點,所以該節點既是頭結點,也是尾節點
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        //LinkedList長度加1
        size++;
        modCount++;
    }

作用:將新物件插入到LinkedList的指定節點前面。