? ? LinkedList是另外一種常見的list實現類,底層基于鏈表實現,不僅實現了List接口,還是實現了Deque接口,所以說LinkedList也是一種隊列。LinkedList是雙向鏈表,它的插入刪除效率較高,但是查詢效率較低(雖然有一定的優化)。first、last表示列表的首尾節點,容量大小用size表示。下面就具體講講LinkedList的源碼。
1.Node節點信息
? ? Node的構造方法已經使node節點插入了鏈表,但此時整個鏈表還不是雙向鏈表。還需要將node前驅的后繼(node.prev.next=node)、后繼的前驅(node.next.prev=node)指向node,如此,整個鏈表構成了雙向鏈表。
2.構造函數
? ? ? LinkedList有兩個構造函數。傳入Collection對象的構造函數調用了addAll(size, c)。
? ? ? addAll(index, c)首先會檢查index和c,檢查通過后用succ保存后繼節點,然后再pred、succ之間插入c的元素并且不停的跟新pred節點,如果pred為空,表示是從首節點插入,所以需要讓first指向newNode;否則使pred的后繼指向newNode。所有元素插入到隊列后,如果succ為空,則last指向pred節點;否則關聯pred與succ,即使succ的前驅指向pred,succ的后繼執行pred。最后修改size和modCount。
3.重要方法
? ? ① linkFirst方法。此方法使構造一個新節點并使first指向新節點。先把first備份,在利用構造函數構造新的首節點。如果原來first為空,表示鏈表為空,則把last指向newNode;否則是原首節點的前驅執行newNode;最后修改size和monCount。
? ? ② linkLast方法。類似linkFirst方法,此方法構造一個新節點,并使last指向新節點。先用l備份last,在創建一個新的節點,并使last指向新節點。如果last為空,意味著原鏈表為空,需要把first指向新節點;否則使l的后繼指向新節點。
? ? ③ linkBefore方法。此方法在succ節點之前插入一個新節點。這里有一個條件,那就是succ不能為空。先利用pred記錄原succ的前驅。在創建一個新節點。succ的前驅指向新節點,再根據pred是否為空判斷到底把first指向新節點還是把pred的后繼指向新節點。
? ? ④ unlinkFirst方法。此方法刪除首節點f。先用next保存f的后繼,在使f的引用指向空(f是首節點所以不用置空f的前驅),使next指向first。如果next為空,則鏈表現在沒有元素,所有last也為空,否則把next.prev也置空,使jvm回收原first的資源。
? ? ⑤ unlinkLast方法。刪除非空尾節點l。類似unlinkFirst方法。先保存前驅,在置空l,接著把前驅賦值給last。最后根據前驅是否為空判斷鏈表是否有元素,根據結果把first賦空或者把現在last的后繼賦空。
? ? ⑥ unlink方法。此方法刪除節點x。主要使x的前驅和后繼直接關聯上即可。這里要說明的如果前驅為空,沒必要再次使x.prev = null。最后還要修改size和modCount。詳細過程請看代碼。
? ? ⑦ node方法。此方法得到指定index序號的元素節點。如果index小于0.5*size,從前往后遍歷尋找序號為index的節點;否則,從后向前遍歷尋找node。
? ? ⑧contains與indexOf方法。如同ArrayList,contains也是利用indexOf判斷元素是否存在。indexOf方法返回元素第一次出現的位置,如果不存在則返回-1.
? ? LinkedList剩下的方法(包括queue接口的方法)主要就是利用size、first、last以及上訴提到的幾個方法實現。很簡潔。
? ? clear方法清空元素。