java8LinkedList原始碼閱讀解析

專注的阿熊發表於2021-06-15

/**

      * Constructs an empty list.

      */

     public LinkedList() {

     }

     /**

      * Constructs a list containing the elements of the specified

      * collection, in the order they are returned by the collection's

      * iterator.

      *

      * @param  c the collection whose elements are to be placed into this list

      * @throws NullPointerException if the specified collection is null

      */

     public LinkedList(Collection<? extends E> c) {

         // 呼叫無參構造,其實就是個空方法

         this();

         // 新增全部元素至 LinkedList

         addAll(c);

     }

     //addAll 方法,此時對於新建的 LinkedList 例項, size=0

     public boolean addAll(Collection<? extends E> c) {

         return addAll(size, c);

     }

     /**

      * Inserts all of the elements in the specified collection into this

      * list, starting at the specified position.  Shifts the element

      * currently at that position (if any) and any subsequent elements to

      * the right (increases their indices).  The new elements will appear

      * in the list in the order that they are returned by the

      * specified collection's iterator.

      *

      * @param index index at which to insert the first element

      *              from the specified collection

      * @param c collection containing elements to be added to this list

      * @return {@code true} if this list changed as a result of the call

      * @throws IndexOutOfBoundsException {@inheritDoc}

      * @throws NullPointerException if the specified collection is null

      */

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

         // 越界檢查

         checkPositionIndex(index);

         // Collection 入參轉換為陣列

         Object[] a = c.toArray();

         // 檢查入參中是否包含元素,如果返回 false ,說明有參構造的 Collection 引數不包含元素

         int numNew = a.length;

         if (numNew == 0)

             return false;

         // 連結串列節點 Node

         Node<E> pred, succ;

         // 驗證 index 是否 ==size ,如果等於,則在連結串列 last 元素後追加新元素

         if (index == size) {

             succ = null;

             pred = last;

         } else {

             // 如不等於,則獲取下標為 index 元素,

             succ = node(index);

             pred = succ.prev;

         }

         // 迴圈入參中的元素

         for (Object o : a) {

             @SuppressWarnings("unchecked") E e = (E) o;

             // 新建一個節點,外匯跟單gendan5.com不包含 next 下一節點

             Node<E> newNode = new Node<>(pred, e, null);

             如果新建節點 next==null ,說明是頭節點

             if (pred == null)

                 first = newNode;

             else

                 // 否則,將前節點的 next 引用指向新建節點

                 pred.next = newNode;

             pred = newNode;

         }

         // 迴圈結束,如果傳入 index 為連結串列長度,最後一次迴圈得到 pred 就是尾節點

         if (succ == null) {

             last = pred;

         } else {

             // 如果 index 不等於 size ,說明是從中間插入的,最後一個元素也有下一節點

             // 該下一節點就是之前下標為 index 的元素

             pred.next = succ;

             succ.prev = pred;

         }

         // 連結串列元素數量增加

         size += numNew;

         // 迭代器需要用到的修改次數,若不為 0 ,使用迭代器遍歷會報錯

         modCount++;

         return true;

     }

     // 越界檢查

     private void checkPositionIndex(int index) {

         if (!isPositionIndex(index))

             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

     }

     // 越界檢查

     private boolean isPositionIndex(int index) {

         return index >= 0 && index <= size;

     }

     // 連結串列中節點,包含自身引用及前後節點引用

     // 這樣,連結串列中的節點便是包含前一節點和後一節點引用 ( 除去首尾節點 )

     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;

         }

     }

     /**

      * Returns the (non-null) Node at the specified element index.

      * 返回指定位置的非空節點

      * 節點如果為空

      */

     Node<E> node(int index) {

         // assert isElementIndex(index);

         //index 大於 size 的一半,則從連結串列頭部開始向下遍歷處理

         if (index < (size >> 1)) {

             Node<E> x = first;

             // 從頭遍歷,找到下標為 index 的元素(同陣列的下標)

             // 也就是說秒如果 index=4 ,得到的,是第五個元素

             for (int i = 0; i < index; i++)

                 x = x.next;

             return x;

         } else {

             // 否則,則從連結串列尾部開始向上遍歷處理

             Node<E> x = last;

             // 從尾巴節點的前節點開始找,假如 size=8.index = 6. 實際得到的,相當於陣列中下標為 7 的元素

             for (int i = size - 1; i > index; i--)

                 x = x.prev;

             return x;

         }

     }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2776807/,如需轉載,請註明出處,否則將追究法律責任。

相關文章