java集合—LinkedList源碼說個明明白白!
1.LinkedList介紹
我們除了最最常用的ArrayList之外,還有LinkedList,這到底是什么東西?從LinkedList官方文檔,我們可以了解到,它其實是實現(xiàn)了List和Queue的雙向鏈表結(jié)構(gòu),而ArrayList底層則是數(shù)組結(jié)構(gòu)。
下面的講解基于jdk 1.8:

繼承了AbstractSequentialList,實現(xiàn)了List,Queue,Cloneable,Serializable,既可以當(dāng)成列表使用,也可以當(dāng)成隊列,堆棧使用。主要特點有:
線程不安全,不同步,如果需要同步需要使用 List list = Collections.synchronizedList(new LinkedList());實現(xiàn) List接口,可以對它進(jìn)行隊列操作實現(xiàn) Queue接口,可以當(dāng)成堆棧或者雙向隊列使用實現(xiàn)Cloneable接口,可以被克隆,淺拷貝 實現(xiàn) Serializable,可以被序列化和反序列化
下面是LinkedList的結(jié)構(gòu),注意:指針結(jié)束指向的是node,開始的是prev或者next

源碼定義如下:
public?class?LinkedList<E>
????extends?AbstractSequentialList<E>
????implements?List<E>,?Deque<E>,?Cloneable,?java.io.Serializable{
????}
2.成員變量
成員變量相對比較簡單,因為不像ArrayList一樣,需要使用數(shù)組保存元素,LinkedList是靠引用來關(guān)聯(lián)前后節(jié)點,所以這里只有大小,第一個節(jié)點,最后一個節(jié)點,以及序列化的uid。
????//?大小
????transient?int?size?=?0;
????//?第一個節(jié)點
????transient?Node?first;
????//?最后一個節(jié)點
????transient?Node?last;
??//?序列化uid
????private?static?final?long?serialVersionUID?=?876323262645176354L;
我們來看看Node到底是何方神圣?其實就是內(nèi)部類,里面的item是真正保存節(jié)點的地方,next是下一個節(jié)點的引用,prev是上一個節(jié)點的引用。這里也體現(xiàn)了LinkedList其實就是雙線鏈表。
只有一個構(gòu)造函數(shù),三個參數(shù)分別對應(yīng)三個屬性。
????private?static?class?Node<E>?{
????????//?節(jié)點里面的數(shù)據(jù)
????????E?item;
????????//?下一個節(jié)點的引用
????????Node?next;
????????//?上一個節(jié)點的引用
????????Node?prev;
????????//?節(jié)點的構(gòu)造函數(shù),重寫之后,無參數(shù)構(gòu)造器已經(jīng)被覆蓋,三個參數(shù)分別對應(yīng)三個屬性
????????Node(Node?prev,?E?element,?Node?next)?{
????????????this.item?=?element;
????????????this.next?=?next;
????????????this.prev?=?prev;
????????}
????}
3. 構(gòu)造函數(shù)
構(gòu)造函數(shù)有兩個,一個是無參數(shù)構(gòu)造函數(shù),另一個是初始化集合元素,里面調(diào)用的其實是addAll,一看就是將里面所有的元素加入到集合中。
????public?LinkedList()?{
????}
????public?LinkedList(Collection?extends?E>?c)?{
????????this();
????????addAll(c);
????}
4. 常用List方法解析
4.1 查找相關(guān)
4.1.1 getFirst()
獲取第一個元素:
????public?E?getFirst()?{
????????//?保存第一個元素為f,注意是final的,
????????final?Node?f?=?first;
????????if?(f?==?null)
????????????//?如果沒有第一個元素,那么就會拋出異常
????????????throw?new?NoSuchElementException();
????????//?返回第一個元素的item
????????return?f.item;
????}
4.1.2 getLast()
獲取最后一個元素,和獲取第一個的原理差不多
????public?E?getLast()?{
????????//?保存最后一個元素的引用為l
????????final?Node?l?=?last;
????????//?如果為空,拋出錯誤
????????if?(l?==?null)
????????????throw?new?NoSuchElementException();
????????//?返回item
????????return?l.item;
????}
4.1.3 get(int index)
通過索引來獲取元素,里面是調(diào)用了另外一個方法先獲取節(jié)點,再獲取該節(jié)點的item,在此之前,做了index安全性校驗。
????public?E?get(int?index)?{
????????checkElementIndex(index);
????????return?node(index).item;
????}
在?上面的代碼中調(diào)用了通過索引位置查找節(jié)點位置的函數(shù),下面我們來分析一下這個函數(shù),由于底層是鏈表實現(xiàn)的,所以呢?遍歷起來不是很方便,就考慮到位運算,如果索引位置在后面一半,就從后往前遍歷查找,否則從前往后遍歷。
????Node?node(int?index)? {
????????//?assert?isElementIndex(index);
????//?size>>1?表示除以2,相當(dāng)于index小于size的一半
????????if?(index?(size?>>?1))?{
???????????//?從前面開始遍歷,取出first節(jié)點,因為中間過程引用會變化,所以不可直接操作first
????????????Node?x?=?first;
???????????//?通過循環(huán)計數(shù)來查找
????????????for?(int?i?=?0;?i?????????????????x?=?x.next;
????????????return?x;
????????}?else?{
???????????//?取出最后一個元素
????????????Node?x?=?last;
???????????//?從后往前遍歷
????????????for?(int?i?=?size?-?1;?i?>?index;?i--)
????????????????x?=?x.prev;
????????????return?x;
????????}
????}
4.1.4 indexOf(Object o)
查找某一個元素的索引位置,分為兩種情況討論,如果要查找的元素為空,那么就使用==,否則使用equals(),這也從側(cè)面印證了LinedList實際上是可以存儲null元素的。使用計數(shù)查找:
????public?int?indexOf(Object?o)?{
????????int?index?=?0;
???????//?如果需要查找null元素
????????if?(o?==?null)?{
????????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)?{
????????????????if?(x.item?==?null)
????????????????????return?index;
????????????????index++;
????????????}
????????}?else?{
???????????//?查找元素不為空
????????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)?{
????????????????if?(o.equals(x.item))
????????????????????return?index;
????????????????index++;
????????????}
????????}
????????return?-1;
????}
4.1.5 lastIndexOf(Object o)
和前面的indexOf差不多,區(qū)別就是這個是后面開始查找,找到第一個符合的元素。
????public?int?indexOf(Object?o)?{
????????int?index?=?0;
???????//?查找元素
????????if?(o?==?null)?{
????????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)?{
????????????????if?(x.item?==?null)
????????????????????return?index;
????????????????index++;
????????????}
????????}?else?{
????????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)?{
????????????????if?(o.equals(x.item))
????????????????????return?index;
????????????????index++;
????????????}
????????}
????????return?-1;
????}
4.2 添加元素
4.2.1 addFirst(E e)
將元素e,添加到第一個節(jié)點,公有方法是addFirst(),但是其實內(nèi)部調(diào)用是linkFirst(),這是private方法。
????public?void?addFirst(E?e)?{
????????linkFirst(e);
????}
????private?void?linkFirst(E?e)?{
????????//?先保存第一個節(jié)點
????????final?Node?f?=?first;
????????//?初始化一個新節(jié)點,prev是null,next是f(之前的首節(jié)點)
????????final?Node?newNode?=?new?Node<>(null,?e,?f);
????????//?更新first為新節(jié)點
????????first?=?newNode;
????????//?如果之前的第一個節(jié)點是空的,那么就說明里面是空的,沒有元素
????????if?(f?==?null)
????????????//?最后一個元素也是新加入的元素
????????????last?=?newNode;
????????else
????????????//?f的prev前置節(jié)點的引用更新為新的節(jié)點
????????????f.prev?=?newNode;
????????//?個數(shù)增加
????????size++;
????????//?修改次數(shù)增加
????????modCount++;
????}
4.2.2 addLast(E e)
將元素添加在鏈表最后,其實內(nèi)部也是直接調(diào)用的private方法linkLast():
????public?void?addLast(E?e)?{
????????linkLast(e);
????}
????void?linkLast(E?e)?{
????????//?保存最后一個節(jié)點的引用
????????final?Node?l?=?last;
????????//?初始化一個節(jié)點,前置節(jié)點指針引用指向之前的最后一個節(jié)點,后續(xù)節(jié)點的引用是null
????????final?Node?newNode?=?new?Node<>(l,?e,?null);
????????//?將最后一個節(jié)點更新
????????last?=?newNode;
????????//?如果之前的最后一個節(jié)點是null,說明鏈表是空的
????????if?(l?==?null)
????????????//?新節(jié)點同時是第一個節(jié)點
????????????first?=?newNode;
????????else
????????????//?否則之前的最后一個節(jié)點的后續(xù)節(jié)點引用更新為新的節(jié)點
????????????l.next?=?newNode;
????????//?大小+1
????????size++;
????????//?修改次數(shù)+1
????????modCount++;
????}
4.2.3 add(E e)
增加元素,默認(rèn)也是在鏈表的最后添加,完成返回true:
????public?boolean?add(E?e)?{
????????linkLast(e);
????????return?true;
????}
4.2.4 addAll(Collection extends E> c)
往鏈表里面批量添加元素,里面默認(rèn)是在最后面批量添加,內(nèi)部調(diào)用的是addAll(int index, Collection extends E> c),添加之前會判斷索引位置是不是合法的。然后查找需要插入的位置的前后節(jié)點,循環(huán)插入。
????public?boolean?addAll(Collection?extends?E>?c)?{
????????return?addAll(size,?c);
????}
????public?boolean?addAll(int?index,?Collection?extends?E>?c)?{
????????//?檢查添加位置
????????checkPositionIndex(index);
????????//?將需要添加的集合轉(zhuǎn)換成為數(shù)組
????????Object[]?a?=?c.toArray();
????????//?獲取數(shù)組的大小
????????int?numNew?=?a.length;
????????//?如果數(shù)組長度為0,說明沒有需要添加的元素,返回false
????????if?(numNew?==?0)
????????????return?false;
????????//?插入位置的前節(jié)點和后續(xù)節(jié)點
????????Node?pred,?succ;
????????//?如果插入位置索引大小等于鏈表大小,那么就是在最后插入元素
????????if?(index?==?size)?{
????????????//?最后插入元素沒有后續(xù)節(jié)點
????????????succ?=?null;
????????????//?前一個節(jié)點就是之前的最后一個節(jié)點
????????????pred?=?last;
????????}?else?{
????????????//?查找到索引為index?的節(jié)點
????????????succ?=?node(index);
????????????//?獲取前一個節(jié)點
????????????pred?=?succ.prev;
????????}
????????
????????//?循環(huán)插入節(jié)點
????????for?(Object?o?:?a)?{
????????????@SuppressWarnings("unchecked")?E?e?=?(E)?o;
????????????//?初始化新節(jié)點,上一個節(jié)點是pred
????????????Node?newNode?=?new?Node<>(pred,?e,?null);
????????????//?如果前一個節(jié)點是null,那么第一個節(jié)點就是新的節(jié)點
????????????if?(pred?==?null)
????????????????first?=?newNode;
????????????else
????????????????//?否則pred的next置為新節(jié)點
????????????????pred.next?=?newNode;
????????????pred?=?newNode;
????????}
????????//?如果插入位置沒有后續(xù)節(jié)點,也就是succ為null
????????if?(succ?==?null)?{
????????????//?最后一個節(jié)點也就是pred,剛剛插入的新節(jié)點
????????????last?=?pred;
????????}?else?{
????????????//?加入所有元素之后的最后一個節(jié)點的下一個節(jié)點指向succ(后續(xù)元素)
????????????pred.next?=?succ;
????????????//?插入位置的后續(xù)元素的上一個節(jié)點引用指向pred
????????????succ.prev?=?pred;
????????}
???????//?大小改變
????????size?+=?numNew;
???????//?修改次數(shù)增加
????????modCount++;
????????return?true;
????}
上面的代碼調(diào)用了node(index),這個在前面查找的時候已經(jīng)說過了,不再解釋。
4.2.5 addAll(int index, Collection extends E> c)
在指定位置批量插入節(jié)點:
????public?boolean?addAll(int?index,?Collection?extends?E>?c)?{
???????//?檢查索引合法性
????????checkPositionIndex(index);
???????//?將需要插入的集合轉(zhuǎn)換成為數(shù)組
????????Object[]?a?=?c.toArray();
???????//?數(shù)組的長度
????????int?numNew?=?a.length;
???????//?為0則不需要插入
????????if?(numNew?==?0)
????????????return?false;
???????//?插入位置的前節(jié)點和后節(jié)點
????????Node?pred,?succ;
???????//?如果在最后插入
????????if?(index?==?size)?{
???????????//?后節(jié)點為空
????????????succ?=?null;
???????????//?前節(jié)點是最后一個
????????????pred?=?last;
????????}?else?{
???????????//?獲取插入位置的后節(jié)點
????????????succ?=?node(index);
???????????//?獲取前節(jié)點
????????????pred?=?succ.prev;
????????}
????
???????//?遍歷
????????for?(Object?o?:?a)?{
????????????@SuppressWarnings("unchecked")?E?e?=?(E)?o;
???????????//?初始化節(jié)點,前置節(jié)點是插入位置的前節(jié)點,后續(xù)節(jié)點為null
????????????Node?newNode?=?new?Node<>(pred,?e,?null);
???????????//?如果插入位置前一個節(jié)點是null,說明插入位置是鏈表首
????????????if?(pred?==?null)
???????????????//?首節(jié)點就是新插入的節(jié)點
????????????????first?=?newNode;
????????????else
???????????????//?前節(jié)點的next指向新節(jié)點
????????????????pred.next?=?newNode;
???????????//?更新插入位置的前一個節(jié)點
????????????pred?=?newNode;
????????}
???????//?如果插入位置的后一個節(jié)點為空,說明插入位置是鏈表尾部
????????if?(succ?==?null)?{
???????????//?最后一個元素就是插入的元素
????????????last?=?pred;
????????}?else?{
???????????//?將插入的最后一個元素next指向succ
????????????pred.next?=?succ;
???????????//?succ的上一個元素指向prev
????????????succ.prev?=?pred;
????????}
???????//?大小更新
????????size?+=?numNew;
???????//?修改次數(shù)改變
????????modCount++;
???????//?返回成功
????????return?true;
????}
4.2.6 add(int index,E element)
將元素插入在指定位置,先判斷索引位置,如果索引位置是最后一個,那么直接調(diào)用在最后添加元素函數(shù)即可,否則需要調(diào)用另外一個函數(shù),在某個元素前面插入:
????public?void?add(int?index,?E?element)?{
???????//?index校驗
????????checkPositionIndex(index);
???????
???????//?索引等于鏈表大小
????????if?(index?==?size)
???????????//?直接在最后插入元素
????????????linkLast(element);
????????else
???????????//?在某個節(jié)點前插入元素
????????????linkBefore(element,?node(index));
????}
4.3 刪除元素
4.3.1 removeFirst()
刪除第一個節(jié)點,先獲取首節(jié)點,判斷第一個節(jié)點是不是為空,如果為空則證明沒有該節(jié)點,拋出異常,內(nèi)部調(diào)用的其實是unlinkFirst()。返回值是被移除的節(jié)點里面的數(shù)值。
????public?E?removeFirst()?{
????????final?Node?f?=?first;
????????if?(f?==?null)
????????????throw?new?NoSuchElementException();
????????return?unlinkFirst(f);
????}
??//?移除首節(jié)點
????private?E?unlinkFirst(Node?f) ?{
????????//?assert?f?==?first?&&?f?!=?null;
???????//?獲取里面的元素
????????final?E?element?=?f.item;
???????//?保存下一個節(jié)點
????????final?Node?next?=?f.next;
???????//?將之前的首節(jié)點前后節(jié)點引用置空,有利于GC
????????f.item?=?null;
????????f.next?=?null;?//?help?GC
???????//?首節(jié)點更新
????????first?=?next;
???????//?如果首節(jié)點是空的,那么鏈表沒有元素了,最后一個節(jié)點自然也是null
????????if?(next?==?null)
????????????last?=?null;
????????else
???????????//?否則當(dāng)前的第一個節(jié)點的前置節(jié)點置null
????????????next.prev?=?null;
???????//?鏈表大小-1
????????size--;
???????//?修改次數(shù)增加
????????modCount++;
????????return?element;
????}
4.3.2 removeLast()
刪除最后一個節(jié)點,和上面的刪除首節(jié)點差不多,先取出最后一個節(jié)點,判斷是否為空,如果為空則拋出異常,否則會調(diào)用另一個解除連接的函數(shù)unLinkLast()。
????public?E?removeLast()?{
????????final?Node?l?=?last;
????????if?(l?==?null)
????????????throw?new?NoSuchElementException();
????????return?unlinkLast(l);
????}
????private?E?unlinkLast(Node?l) ?{
????????//?assert?l?==?last?&&?l?!=?null;
???????//?保存被移除的節(jié)點的item
????????final?E?element?=?l.item;
???????//?獲取上一個節(jié)點
????????final?Node?prev?=?l.prev;
???????//?前后引用置空,有利于垃圾回收
????????l.item?=?null;
????????l.prev?=?null;?//?help?GC
???????//?更新最后一個節(jié)點
????????last?=?prev;
???????//?如果前置節(jié)點為空,那么鏈表已經(jīng)沒有元素了
????????if?(prev?==?null)
????????????first?=?null;
????????else
???????????//?否則將上一個節(jié)點的next置null
????????????prev.next?=?null;
???????//?大小該表
????????size--;
???????//?修改次數(shù)增加
????????modCount++;
???????//?返回被移除的節(jié)點的item值
????????return?element;
????}
4.3.3 remove(Object o)
刪除某個元素分為兩種情況,元素為null和非null,直接遍歷判斷,里面真正刪除的方法其實是unlink(E e),成功移除則返回true,注意這里只會移除掉第一個,后續(xù)要是還有該節(jié)點,不會移除。
????public?boolean?remove(Object?o)?{
???????//?元素為null
????????if?(o?==?null)?{
????????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)?{
????????????????if?(x.item?==?null)?{
????????????????????unlink(x);
????????????????????return?true;
????????????????}
????????????}
????????}?else?{
???????????//?元素不為null
????????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)?{
????????????????if?(o.equals(x.item))?{
???????????????????//?移除節(jié)點
????????????????????unlink(x);
????????????????????return?true;
????????????????}
????????????}
????????}
????????return?false;
????}
unLink(E e)方法如下:
????E?unlink(Node?x) ?{
????????//?assert?x?!=?null;
???????//?保存被移除節(jié)點的item
????????final?E?element?=?x.item;
???????//?下一個節(jié)點
????????final?Node?next?=?x.next;
???????//?上一個節(jié)點
????????final?Node?prev?=?x.prev;
???????//?如果前置節(jié)點為空,那么首節(jié)點就是當(dāng)前節(jié)點了
????????if?(prev?==?null)?{
????????????first?=?next;
????????}?else?{
???????????//?前一個節(jié)點的next置為下一個節(jié)點
????????????prev.next?=?next;
???????????//?之前的節(jié)點的前一個節(jié)點置null
????????????x.prev?=?null;
????????}
???????//?如果next是空的,那么上一個節(jié)點就是現(xiàn)在最后一個節(jié)點
????????if?(next?==?null)?{
????????????last?=?prev;
????????}?else?{
???????????//?next的上一個節(jié)點引用指向prev
????????????next.prev?=?prev;
???????????//?被刪除的元素的next置空
????????????x.next?=?null;
????????}
???????//?item置空
????????x.item?=?null;
???????//?大小改變
????????size--;
???????//?修改次數(shù)增加
????????modCount++;
???????//?返回被刪除的節(jié)點里面的item
????????return?element;
????}
4.3.4 clear()
移除里面所有的元素:
????public?void?clear()?{
????????//?Clearing?all?of?the?links?between?nodes?is?"unnecessary",?but:
????????//?-?helps?a?generational?GC?if?the?discarded?nodes?inhabit
????????//???more?than?one?generation
????????//?-?is?sure?to?free?memory?even?if?there?is?a?reachable?Iterator
????????for?(Node?x?=?first;?x?!=?null;?)?{
???????????//?保存下一個
????????????Node?next?=?x.next;
???????????//?當(dāng)前元素置空
????????????x.item?=?null;
????????????x.next?=?null;
????????????x.prev?=?null;
????????????x?=?next;
????????}
???????//?首節(jié)點和尾節(jié)點全部置null
????????first?=?last?=?null;
????????size?=?0;
????????modCount++;
????}
4.3.5 remove(int index)
移除指定索引的元素。先通過索引找到節(jié)點,再移除指定的節(jié)點
????public?E?remove(int?index)?{
???????//?檢查合法性
????????checkElementIndex(index);
???????//?先找到節(jié)點,再移除指定節(jié)點
????????return?unlink(node(index));
????}
4.4 更新元素
4.4.1 set(int index,E element)
更新指定索引的位置的元素,首先通過索引查找到該元素,然后修改item值,返回舊的item值。
????public?E?set(int?index,?E?element)?{
???????//?檢查索引是否合法
????????checkElementIndex(index);
???????//?通過索引查找到節(jié)點
????????Node?x?=?node(index);
???????//?保存舊的值
????????E?oldVal?=?x.item;
???????//?修改
????????x.item?=?element;
???????//?返回舊的元素
????????return?oldVal;
????}
5 queue相關(guān)的方法
因為LinkedList也實現(xiàn)了queue接口,所以它肯定也實現(xiàn)了相關(guān)的方法,下面我們看看:
5.1 peek()
獲取隊列第一個元素:
????public?E?peek()?{
???????//?拿到第一個元素,final不可變
????????final?Node?f?=?first;
???????//?返回item值
????????return?(f?==?null)???null?:?f.item;
????}
5.2 element()
也是獲取隊列第一個元素,里面調(diào)用的是getFirst()。
????public?E?element()?{
????????return?getFirst();
????}
5.3 poll()
移除隊列第一個節(jié)點元素并返回,里面調(diào)用的其實是unlinkFirst()
????public?E?poll()?{
???????//?獲取到第一個元素
????????final?Node?f?=?first;
???????//?移除并返回
????????return?(f?==?null)???null?:?unlinkFirst(f);
????}
5.4 remove()
移除隊列第一個元素,里面調(diào)用的是removeFirst():
????public?E?remove()?{
????????return?removeFirst();
????}
5.5 offfer(E e)
在隊列后面增加元素:
????public?boolean?offer(E?e)?{
????????return?add(e);
????}
5.6 offerFirst(E e)
往隊列的前面插入元素,其實調(diào)用的是addFirst()
????public?boolean?offerFirst(E?e)?{
????????addFirst(e);
????????return?true;
????}
5.7 offerLast(E e)
往隊列的后面添加元素,其實調(diào)用的是addList()
????public?boolean?offerLast(E?e)?{
????????addLast(e);
????????return?true;
????}
5.8 peekFirst()
獲取第一個節(jié)點里面的元素:
????public?E?peekFirst()?{
????????final?Node?f?=?first;
????????return?(f?==?null)???null?:?f.item;
?????}
5.9 peekLast()
獲取最后一個節(jié)點的元素:
????public?E?peekLast()?{
????????final?Node?l?=?last;
????????return?(l?==?null)???null?:?l.item;
????}
5.10 pollFirst()
獲取第一個元素,并且移除它,使用的是unlinkFirst(E e)
????public?E?pollFirst()?{
????????final?Node?f?=?first;
????????return?(f?==?null)???null?:?unlinkFirst(f);
????}
5.11 pollLast()
獲取隊列最后一個元素,并且移除它,調(diào)用的其實是unlinkLast(E e)
????public?E?pollLast()?{
????????final?Node?l?=?last;
????????return?(l?==?null)???null?:?unlinkLast(l);
????}
5.12 push(E e)
像是堆棧的特點,在前面添加元素:
????public?void?push(E?e)?{
????????addFirst(e);
????}
5.13 pop()
堆棧的特點,取出隊列首的第一個元素
????public?E?pop()?{
????????return?removeFirst();
????}
5.14 removeFirstOccurrence(Object o)
移除元素,從前往后第一次出現(xiàn)的地方移除掉:
????public?boolean?removeFirstOccurrence(Object?o)?{
????????return?remove(o);
????}
5.15 removeLastOccurrence(Object o)
移除元素,最后一次出現(xiàn)的地方移除掉,和前面分析的一樣,分為兩種情況,null和非null。
????public?boolean?removeLastOccurrence(Object?o)?{
???????//?元素為null
????????if?(o?==?null)?{
????????????for?(Node?x?=?last;?x?!=?null;?x?=?x.prev)?{
????????????????if?(x.item?==?null)?{
????????????????????unlink(x);
????????????????????return?true;
????????????????}
????????????}
????????}?else?{
???????????//?元素不是null
????????????for?(Node?x?=?last;?x?!=?null;?x?=?x.prev)?{
????????????????if?(o.equals(x.item))?{
????????????????????unlink(x);
????????????????????return?true;
????????????????}
????????????}
????????}
????????return?false;
????}
6.其他方法
是否包含某個元素,其實調(diào)用的是indexOf()方法,如果返回的索引不為-1,則包含:
????public?boolean?contains(Object?o)?{
????????return?indexOf(o)?!=?-1;
????}
返回大小:
????public?int?size()?{
????????return?size;
????}
是否為有效元素下標(biāo)索引,從0到size-1
????private?boolean?isElementIndex(int?index)?{
????????return?index?>=?0?&&?index?????}
是否為有效位置索引,從0到size
????private?boolean?isPositionIndex(int?index)?{
????????return?index?>=?0?&&?index?<=?size;
????}
獲取指定索引位置的ListIterator:
????public?ListIterator?listIterator(int?index)? {
???????//?檢查合法性
????????checkPositionIndex(index);
????????return?new?ListItr(index);
????}
獲取倒序的迭代器:
????public?Iterator?descendingIterator()? {
????????return?new?DescendingIterator();
????}
拷貝克隆函數(shù),一個是父類的克隆函數(shù),另一個是重寫的克隆函數(shù),這里比較特殊,因為LinkedList是鏈表,本身只保存了第一個和最后一個的引用,所以拷貝的時候需要向里面添加元素的方式進(jìn)行拷貝。
????public?Object?clone()?{
????????LinkedList?clone?=?superClone();
????????//?Put?clone?into?"virgin"?state
????????clone.first?=?clone.last?=?null;
????????clone.size?=?0;
????????clone.modCount?=?0;
????????//?添加元素到拷貝的隊列中
????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)
????????????clone.add(x.item);
????????return?clone;
????}
????private?LinkedList?superClone()? {
????????try?{
????????????return?(LinkedList)?super.clone();
????????}?catch?(CloneNotSupportedException?e)?{
????????????throw?new?InternalError(e);
????????}
????}
轉(zhuǎn)換成為數(shù)組,通過循環(huán)實現(xiàn)
????public?Object[]?toArray()?{
????????Object[]?result?=?new?Object[size];
????????int?i?=?0;
???????//?循環(huán)實現(xiàn)
????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)
????????????result[i++]?=?x.item;
????????return?result;
????}
轉(zhuǎn)換成為指定類型的數(shù)組,和前面不同的是,這里初始化的時候使用類型反射創(chuàng)建(T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size)
????public??T[]?toArray(T[]?a)?{
????????if?(a.length?????????????a?=?(T[])java.lang.reflect.Array.newInstance(
????????????????????????????????a.getClass().getComponentType(),?size);
????????int?i?=?0;
????????Object[]?result?=?a;
????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)
????????????result[i++]?=?x.item;
????????if?(a.length?>?size)
????????????a[size]?=?null;
????????return?a;
????}
獲取可分割迭代器:
????public?Spliterator?spliterator()? {
????????return?new?LLSpliterator(this,?-1,?0);
????}
7.迭代器
里面定義了三種迭代器,都是以內(nèi)部類的方式實現(xiàn),分別是:
ListItr:列表的經(jīng)典迭代器 DescendingIterator:倒序迭代器 LLSpliterator:可分割迭代器
7.1 ListItr
先來說說ListItr,這個迭代器主要是有next(),hashNext(),hasPrevious(),previous(),nextIndex(),previousIndex(),remove(),set(),add(),forEachRemaining()方法:
next():獲取下一個元素hashNext():是否有下一個元素hasPrevious():是否有上一個元素previous():上一個元素nextIndex():下一個索引位置previousIndex():上一個索引位置remove():刪除當(dāng)前索引位置的元素set():更新元素add():新增元素forEachRemaining():遍歷剩下的元素
里面主要有集合重要的屬性:
lastReturned:上一次返回的元素next:下一個返回的元素nextIndex:下一個索引expectedModCount:期待修改的次數(shù)
????private?class?ListItr?implements?ListIterator<E>?{
???????//?上一個返回的元素
????????private?Node?lastReturned;
???????//?下一個元素
????????private?Node?next;
???????//?下一個索引
????????private?int?nextIndex;
???????//?期待的修改次數(shù)
????????private?int?expectedModCount?=?modCount;
???????
???????//?初始化
????????ListItr(int?index)?{
????????????//?根據(jù)索引位置更新下一個返回的節(jié)點
????????????next?=?(index?==?size)???null?:?node(index);
???????????//?更新索引
????????????nextIndex?=?index;
????????}
???????//?是否有下一個元素:索引是否小于size
????????public?boolean?hasNext()?{
????????????return?nextIndex?????????}
???????//?獲取下一個元素
????????public?E?next()?{
???????????//?檢查修改合法化
????????????checkForComodification();
???????????//?如果沒有下一個元素會拋異常,所以使用前需要先判斷
????????????if?(!hasNext())
????????????????throw?new?NoSuchElementException();
???????????//?上一次返回的元素更新
????????????lastReturned?=?next;
???????????//?更新下一次返回的元素
????????????next?=?next.next;
???????????//?更新索引
????????????nextIndex++;
???????????//?返回item
????????????return?lastReturned.item;
????????}
??????
???????//?是否有上一個:下一個返回的元素索引是不是大于0
????????public?boolean?hasPrevious()?{
????????????return?nextIndex?>?0;
????????}
???????//?返回上一個元素
????????public?E?previous()?{
???????????//?檢查
????????????checkForComodification();
???????????//?判斷是否有上一個元素??
???????????if?(!hasPrevious())
????????????????throw?new?NoSuchElementException();
???????????//?上一個返回的元素,需要更新
????????????lastReturned?=?next?=?(next?==?null)???last?:?next.prev;
????????????//?更新索引
???????????nextIndex--;
????????????return?lastReturned.item;
????????}
???????//?下一個索引
????????public?int?nextIndex()?{
????????????return?nextIndex;
????????}
???????//?上一個索引
????????public?int?previousIndex()?{
????????????return?nextIndex?-?1;
????????}
?
???????//?移除當(dāng)前位置的索引
????????public?void?remove()?{
???????????//?檢查修改合法性
????????????checkForComodification();
????????????if?(lastReturned?==?null)
????????????????throw?new?IllegalStateException();
??????//?獲取下一個元素
????????????Node?lastNext?=?lastReturned.next;
???????????//?移除上一個返回的元素
????????????unlink(lastReturned);
???????????//?如果下一個是上次返回的元素,那么下一個元素需要更新,因為該元素已經(jīng)被移除了
????????????if?(next?==?lastReturned)
????????????????next?=?lastNext;
????????????else
???????????????//?更新索引
????????????????nextIndex--;
????????????lastReturned?=?null;
????????????expectedModCount++;
????????}
???????//?更新
????????public?void?set(E?e)?{
????????????if?(lastReturned?==?null)
????????????????throw?new?IllegalStateException();
????????????checkForComodification();
????????????lastReturned.item?=?e;
????????}
????????public?void?add(E?e)?{
????????????checkForComodification();
????????????lastReturned?=?null;
???????????//?如果下一個元素是空,那就是在隊尾添加元素
????????????if?(next?==?null)
????????????????linkLast(e);
????????????else
???????????????//?否則就是在next索引處添加元素
????????????????linkBefore(e,?next);
???????????//?更新索引
????????????nextIndex++;
????????????expectedModCount++;
????????}
????
???????//?遍歷剩下的元素
????????public?void?forEachRemaining(Consumer?super?E>?action)?{
????????????Objects.requireNonNull(action);
???????????//?使用循環(huán),索引不斷后移,遍歷
????????????while?(modCount?==?expectedModCount?&&?nextIndex????????????????//?對每個節(jié)點元素執(zhí)行操作
????????????????action.accept(next.item);
????????????????lastReturned?=?next;
????????????????next?=?next.next;
????????????????nextIndex++;
????????????}
????????????checkForComodification();
????????}
????????final?void?checkForComodification()?{
????????????if?(modCount?!=?expectedModCount)
????????????????throw?new?ConcurrentModificationException();
????????}
????}
上面的迭代器沒有什么好說的,就是往前面和后面遍歷的功能,以及增刪改的功能。
7.2 DescendingIterator
這個迭代器有點意思,也很簡單,就是一個倒序的功能,功能實現(xiàn)也十分簡單:
hasNext:是否有下一個元素,實際上是判斷上一個元素 next:獲取下一個元素,實際上是獲取前面一個元素 remove:移除元素
倒序就是別人從前往后,它偏偏從后往前遍歷,emmmmmmm
????private?class?DescendingIterator?implements?Iterator<E>?{
????????private?final?ListItr?itr?=?new?ListItr(size());
????????public?boolean?hasNext()?{
????????????return?itr.hasPrevious();
????????}
????????public?E?next()?{
????????????return?itr.previous();
????????}
????????public?void?remove()?{
????????????itr.remove();
????????}
????}
7.3 LLSpliterator
這個迭代器有點東西,感覺和其它的不太一樣,LLSpliterator是在使用node的next進(jìn)行迭代,下面分析一下:主要是為了將元素分為多份,然后再用多線程來處理。
值得注意的是:分割的時候,LinkedList不是1/2分割,而是每一次分割出來的大小都是遞增的,遞增的大小是BATCH_UNIT,但是返回的不是LLSpliterator,而是ArraySpliterator,每次都分割出更多的元素,轉(zhuǎn)成數(shù)組結(jié)構(gòu),這也許是出自于性能考慮,比較指針遍歷太慢了,我猜的的...別打我
????static?final?class?LLSpliterator<E>?implements?Spliterator<E>?{
???????//?分割長度增加單位
????????static?final?int?BATCH_UNIT?=?1?<10;??//?batch?array?size?increment
???????//?最大分割長度
????????static?final?int?MAX_BATCH?=?1?<25;??//?max?batch?array?size;
????????final?LinkedList?list;?//?null?OK?unless?traversed
???????//?當(dāng)前節(jié)點
????????Node?current;??????//?current?node;?null?until?initialized
???????//?大小估算
????????int?est;??
???????//?期待修改的次數(shù)
????????int?expectedModCount;?//?initialized?when?est?set
???????//?分割長度
????????int?batch;????????????//?batch?size?for?splits
????????LLSpliterator(LinkedList?list,?int?est,?int?expectedModCount)?{
????????????this.list?=?list;
????????????this.est?=?est;
????????????this.expectedModCount?=?expectedModCount;
????????}
????????final?int?getEst()?{
????????????int?s;?//?force?initialization
????????????final?LinkedList?lst;
????????????if?((s?=?est)?0)?{
????????????????if?((lst?=?list)?==?null)
????????????????????s?=?est?=?0;
????????????????else?{
????????????????????expectedModCount?=?lst.modCount;
????????????????????current?=?lst.first;
????????????????????s?=?est?=?lst.size;
????????????????}
????????????}
????????????return?s;
????????}
????//?估算大小
????????public?long?estimateSize()?{?return?(long)?getEst();?}
???????//?分割
????????public?Spliterator?trySplit()? {
????????????Node?p;
???????????//?獲取大小
????????????int?s?=?getEst();
???????????//?當(dāng)前節(jié)點不為空
????????????if?(s?>?1?&&?(p?=?current)?!=?null)?{
???????????????//?分割位置結(jié)束:分割位置+分割單位
????????????????int?n?=?batch?+?BATCH_UNIT;
???????????????//?如果大于大小,就限制最后的位置
????????????????if?(n?>?s)
????????????????????n?=?s;
???????????????//?最大的分割位置
????????????????if?(n?>?MAX_BATCH)
????????????????????n?=?MAX_BATCH;
???????????????//?數(shù)組
????????????????Object[]?a?=?new?Object[n];
????????????????int?j?=?0;
???????????????//?將當(dāng)前位置到n的位置循環(huán),存放到a數(shù)組中
????????????????do?{?a[j++]?=?p.item;?}?while?((p?=?p.next)?!=?null?&&?j?????????????????current?=?p;
????????????????batch?=?j;
????????????????est?=?s?-?j;
???????????????//?ArraySpliterator每次分割成一半一半,而IteratorSpliterator算術(shù)遞增
????????????????return?Spliterators.spliterator(a,?0,?j,?Spliterator.ORDERED);
????????????}
????????????return?null;
????????}
???????//?對剩下的元素進(jìn)行處理
????????public?void?forEachRemaining(Consumer?super?E>?action)?{
????????????Node?p;?int?n;
????????????if?(action?==?null)?throw?new?NullPointerException();
????????????if?((n?=?getEst())?>?0?&&?(p?=?current)?!=?null)?{
????????????????current?=?null;
????????????????est?=?0;
????????????????do?{
????????????????????E?e?=?p.item;
????????????????????p?=?p.next;
????????????????????action.accept(e);
????????????????}?while?(p?!=?null?&&?--n?>?0);
????????????}
????????????if?(list.modCount?!=?expectedModCount)
????????????????throw?new?ConcurrentModificationException();
????????}
???????//?對后面一個元素進(jìn)行處理
????????public?boolean?tryAdvance(Consumer?super?E>?action)?{
????????????Node?p;
????????????if?(action?==?null)?throw?new?NullPointerException();
????????????if?(getEst()?>?0?&&?(p?=?current)?!=?null)?{
????????????????--est;
????????????????E?e?=?p.item;
????????????????current?=?p.next;
????????????????action.accept(e);
????????????????if?(list.modCount?!=?expectedModCount)
????????????????????throw?new?ConcurrentModificationException();
????????????????return?true;
????????????}
????????????return?false;
????????}
????????public?int?characteristics()?{
????????????return?Spliterator.ORDERED?|?Spliterator.SIZED?|?Spliterator.SUBSIZED;
????????}
????}
8.序列化和反序列化
序列化和反序列化的時候,需要重寫,因為我們保存的只有第一個和最后一個節(jié)點的引用,我們序列化需要保存大小和引用,所以需要重寫,要不反序列化回來就找不到next,節(jié)點之間的關(guān)系就會丟失。
序列化的時候如下,寫入了size,以及遍歷的時候?qū)⒐?jié)點的item值寫入。
????private?void?writeObject(java.io.ObjectOutputStream?s)
????????throws?java.io.IOException?{
????????//?Write?out?any?hidden?serialization?magic
????????s.defaultWriteObject();
????????//?Write?out?size
????????s.writeInt(size);
????????//?Write?out?all?elements?in?the?proper?order.
????????for?(Node?x?=?first;?x?!=?null;?x?=?x.next)
????????????s.writeObject(x.item);
????}
反序列化的時候,讀入大小size以及每個節(jié)點里面的元素item
????private?void?readObject(java.io.ObjectInputStream?s)
????????throws?java.io.IOException,?ClassNotFoundException?{
????????//?默認(rèn)序列化
????????s.defaultReadObject();
????????//?大小
????????int?size?=?s.readInt();
????????//?按照順序讀入元素
????????for?(int?i?=?0;?i?????????????linkLast((E)s.readObject());
????}
9.總結(jié)一下
LinkedList底層是用鏈表實現(xiàn)的,而且是雙向鏈表,并且實現(xiàn)了Queue接口,可以當(dāng)成雙向隊列或者堆棧來使用。也正是因為是鏈表實現(xiàn),所以刪除元素比較快,但是查找的時候相對較慢。當(dāng)然,也沒有什么擴(kuò)容,除非就是內(nèi)存不夠了。雙向鏈表,可以從頭往尾遍歷,也可以從尾部往前遍歷。 LinkedList繼承了AbstractSequentialList,AbstractSequentialList實現(xiàn)了get,set,add,remove等方法。序列化/反序列化的時候重寫了方法,才能達(dá)到序列化里面每一個節(jié)點元素的效果。 線程不安全

