LinkedList原始碼(add方法)

歐小文大叔發表於2020-05-19

  對於要有紮實的java基礎,集合是必須掌握的,而且精讀這部分的原始碼很有用,也很有必要。而LinkedList是在java.util包下,和java.io,java.lang都是比較常用,而且比較簡單。看看它們的原始碼有助於鍛鍊我們看原始碼的感覺,也瞭解一下大神們寫程式碼的風格。看這些原始碼的目的,更多是為了增加閱讀程式碼能力。

  這裡只寫LinkedList的初始化和add()方法的原始碼分析,先放一張Collection集合的分類簡圖: 

  LinkedList採用雙向連結串列儲存方式

  

  缺點:遍歷和隨機訪問元素效率低下。

  優點:插入,刪除元素效率比較高(但是前提也是必須先低效率查詢才可,如果插入刪除發生在頭尾可以減少查詢次數)。

  

  那開始吧!

1 public class TestLinkedList {
2 
3     public static void main(String[] args) {
4         LinkedList<Integer> list = new LinkedList<Integer>();
5         list.add(1);
6         list.add(2);
7         list.add(3);
8     }
9 }

  點進LinkedList發現只是一個建構函式,有3個變數(這裡只放部分程式碼)

 1 public class LinkedList<E>
 2     extends AbstractSequentialList<E>
 3     implements List<E>, Deque<E>, Cloneable, java.io.Serializable
 4 {
 5     transient int size = 0; //預設長度0
 6     transient Node<E> first; //上一個元素
 7     transient Node<E> last; //下一個元素
 8 
 9     public LinkedList() {
10     }
11 
12      private static class Node<E> {
13         E item;
14         Node<E> next;
15         Node<E> prev;
16 
17         Node(Node<E> prev, E element, Node<E> next) {
18             this.item = element;
19             this.next = next;
20             this.prev = prev;
21         }
22     }
23 
24 
25 }

  Node是LinkedList的一個內部類,Node指的是雙向連結串列的結點(包括3部分,中間資料item,左右兩邊的指標,指向前prevnext的結點)

  執行到LinkedList<Integer> list = new LinkedList<Integer>();在記憶體中是這樣的

  我們再看看add()方法

 1 public boolean add(E e) {
 2         linkLast(e);
 3         return true;
 4 }
 5 
 6 /**
 7      * Links e as last element.//將e連結為最後一個元素
 8      */
 9     void linkLast(E e) {
10         final Node<E> l = last;
11         final Node<E> newNode = new Node<>(l, e, null);
12         last = newNode;
13         if (l == null)
14             first = newNode;
15         else
16             l.next = newNode;
17         size++;
18         modCount++;
19     }

執行add(1)方法後,將開始last=null賦給了一個變數l,這時候new Node<>(l, e, null);就是new Node<>(null, 1, null),在棧裡建立了物件(Node結點)。

到了12行last = newNode;last就不是null了,是0x2012,也就指向了下一個結點

在往後面看if判斷,這是l是等於null的,就把first = newNode;first就不是null了,是0x2012(newCode),也就指向了上一個結點。因為只有一個結點,前後都是它自己。

繼續add,l=0x2012,所以new Node<>(l, e, null);就是new Node<>(0x2012, 2, null),所以新增的結點就指向了上一個0x2012。

然後再last=newNode,就是0x3012。它就不執行0x2012了。

這個時候if判斷,l已經不等空了,執行l.next=newNode。newNode是0x3012,l是0x2012,l.next就是0x2012這個結點的next屬性,也是個Node。

記憶體圖是這樣的:

最後再add

 

相關文章