LinkedList 是List的一個實現類,並實現了Deque、Cloneable、Serializable 接口
實現 Deque 表示 LinkList 是一個雙向隊列
實現 Cloneable 表示LinkedList 可以被克隆
實現 Serializable 表示LinkedList 可以被序列化
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
// 當前節點數
transient int size = 0;
// 指向第一個節點
transient Node<E> first;
// 指向最後一個節點
transient Node<E> last;
}
一、構造函數
// 無參構造
public LinkedList() {
}
// 集合構造
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
LinkedList 有兩種構造函數,如上所示。無參構造函數不需要過多解釋,就是創建一個空集合。集合構造函數就是把該Collection集合轉化爲一個LinkedList 並返回。
二、add 函數
我們先從具體的函數實現來看以下 這到底是不是雙向鏈表的結構(雖然全局變量有 first last ),及如何把新的元素添加到雙向鏈表上面的。
public boolean add(E e) {
linkLast(e);
return true;
}
可以看出,在新添加元素時,默認添加到尾部,進入linkLast 方法 看具體的實現:
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++;
}
當添加第一個元素的時候,last first 皆爲 null ,因爲在添加元素前,該集合爲空。所以在第一次添加元素的時候 上述代碼第二行 l 爲null,那麼可以繼續看下Node 對應的構造函數:
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;
}
}
由於 當前只添加了一個元素,所以 Node 對應的 前一個元素的指向prev 及 後一個元素的指向 next 皆爲null。由於默認爲向集合尾部添加,所以新創建的Node節點指向last,由於第一次添加,所以 l == null ,在 linkLast 函數中第六行 該元素又被指向last。每次添加一個新元素時候 size自增1,代表整個集合中元素的個數。此時 集合中只有一個元素,該元素的前一個元素指向自身,後一個元素也是指向自身。
接下來繼續添加第二個元素,爲了方便觀察,先把 linkLast 函數複製過來:
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++;
}
此時第一個元素賦值給 l ,並創建一個新的Node節點,此Node節點的prev 指向之前添加的元素。並把新創建的Node節點賦給last , 把 l 的下一個節點指向 新創建的節點( l.next = newNode )。此時集合中有兩個元素,基本就能確定該集合具體是什麼結構的集合,可以回顧下,第二次添加的元素 在創建新的Node節點時,新節點的 prev 指向第一個節點,而 第一個節點的next 指向新創建的節點,用圖表示如下所示:
通過上圖我們應該可以更好的理解 LinkedList 的結構 及 什麼樣的結構是雙向鏈表。當添加新的元素時,無論是 linkLast(向後添加),還是 linkBefore(前面插入),需要做的只是改變 元素 prev 和 next 的指向。由此我們也能得出一個結論 那就是LinkedList 的數據結構 插入與刪除的效率是非常高的(畢竟只是改變指向)。
其他的函數 如 addAll removeLast 等函數在此就不再 細看,原理相通,此文只是讓我們更好的理解LinkedList 的數據結構 及 什麼樣的結構是雙向鏈表。