從JDK1.7開始,LinkedList 由雙向循環鏈表改為雙向鏈表
首先,簡單介紹一下LinkedList:
LinkedList是List接口的雙向鏈表實現。由於是鏈表結構,所以長度沒有限制;而且添加/刪除元素的時候,只需要改變指針的指向(把鏈表斷開,插入/刪除元素,再把鏈表連起來)即可,非常方便,而ArrayList卻需要重整數組 (add/remove中間元素)。所以LinkedList適合用於添加/刪除操作頻繁的情況。
在JDK 1.7之前(此處使用JDK1.6來舉例),LinkedList是通過headerEntry實現的一個循環鏈表的。先初始化一個空的Entry,用來做header,然后首尾相連,形成一個循環鏈表:
在LinkedList中提供了兩個基本屬性size、header。
private transient Entry<E> header = new Entry<E>(null, null, null); private transient int size = 0;
其中size表示的LinkedList的大小,header表示鏈表的表頭,Entry為節點對象。
1 private static class Entry<E> { 2 E element; //元素節點 3 Entry<E> next; //下一個元素 4 Entry<E> previous; //上一個元素 5 6 Entry(E element, Entry<E> next, Entry<E> previous) { 7 this.element = element; 8 this.next = next; 9 this.previous = previous; 10 } 11 }
每次添加/刪除元素都是默認在鏈尾操作。對應此處,就是在header前面操作,因為遍歷是next方向的,所以在header前面操作,就相當於在鏈表尾操作。
如下面的插入操作addBefore以及圖示,如果插入obj_3,只需要修改header.previous和obj_2.next指向obj_3即可。
1 private Entry<E> addBefore(E e, Entry<E> entry) { 2 //利用Entry構造函數構建一個新節點 newEntry, 3 Entry<E> newEntry = new Entry<E>(e, entry, entry.previous); 4 //修改newEntry的前后節點的引用,確保其鏈表的引用關系是正確的 5 newEntry.previous.next = newEntry; 6 newEntry.next.previous = newEntry; 7 //容量+1 8 size++; 9 //修改次數+1 10 modCount++; 11 return newEntry; 12 }
在addBefore方法中無非就是做了這件事:構建一個新節點newEntry,然后修改其前后的引用。
##########################################################################################################################################
在JDK 1.7,1.6的headerEntry循環鏈表被替換成了first和last組成的非循環鏈表。
transient int size = 0; /** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first; /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node<E> last;
在初始化的時候,不用去new一個Entry。
/** * Constructs an empty list. */ public LinkedList() { }
在插入/刪除的時候,也是默認在鏈尾操作。把插入的obj當成newLast,掛在oldLast的后面。另外還要先判斷first是否為空,如果為空則first = obj。
如下面的插入方法linkLast,在尾部操作,只需要把obj_3.next指向obj_4即可。
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++; }
其中:
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; } }
