http://blog.csdn.net/mra__s__/article/details/55517204html
http://www.cnblogs.com/chenssy/p/3746600.htmljava
版權聲明:本文爲博主原創文章,未經博主容許不得轉載。node
(1)LinkedList的內部實現是雙向鏈表,繼承了AbstractSequentialList,實現了List, Deque, Cloneable, Java.io.Serializable接口,所以LinkdeList自己支持就支持雙端隊列操做。LinkedList**容許全部元素(包括 null)**。除了實現 List 接口外,LinkedList 類還爲在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方法。這些操做容許將連接列表用做堆棧、隊列或雙端隊列。markdown
此類實現 Deque 接口,爲 add、poll 提供先進先出隊列操做,以及其餘堆棧和雙端隊列操做。
LinkedList與ArrayList同樣實現List接口,只是ArrayList是List接口的大小可變數組的實現,LinkedList是List接口鏈表的實現。基於鏈表實現的方式使得LinkedList在插入和刪除時更優於ArrayList,而隨機訪問則比ArrayList遜色些。併發
(2)此實現不是同步的。若是多個線程同時訪問一個連接列表,而其中至少一個線程從結構上修改了該列表,則它必須 保持外部同步。(結構修改指添加或刪除一個或多個元素的任何操做;僅設置元素的值不是結構修改。)這通常經過對天然封裝該列表的對象進行同步操做來完成。若是不存在這樣的對象,則應該使用 Collections.synchronizedList 方法來「包裝」該列表。最好在建立時完成這一操做,以防止對列表進行意外的不一樣步訪問,以下所示:函數
List list = Collections.synchronizedList(new LinkedList(...));
(3) 此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗 的:在迭代器建立以後,若是從結構上對列表進行修改,除非經過迭代器自身的 remove 或 add 方法,其餘任什麼時候間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。所以,面對併發的修改,迭代器很快就會徹底失敗,而不冒未來不肯定的時間任意發生不肯定行爲的風險。post
注意,迭代器的快速失敗行爲不能獲得保證,通常來講,存在不一樣步的併發修改時,不可能做出任何硬性保證。快速失敗迭代器盡最大努力拋出 ConcurrentModificationException。所以,編寫依賴於此異常的程序的方式是錯誤的,正確作法是:迭代器的快速失敗行爲應該僅用於檢測程序錯誤。this
(4)和ArrayList相似,在類內部一樣出現了transient關鍵字,這在ArrayList中已經解釋過了,在這裏不作過多的解釋了。spa
transient int size = 0; transient Node<E> first; transient Node<E> last;
1>LinkedList內部經過Node來抽象一個節點,結點包括值和前向指針和後向指針。Node的定義是在LinkedList內部,做爲靜態內部類存在。
private static class Node<E> { E item;//結點的值 Node<E> next;//結點的後向指針 Node<E> prev;//結點的前向指針 //構造函數中已完成Node成員的賦值 Node(Node<E> prev, E element, Node<E> next) { this.item = element;//結點的值賦值爲element this.next = next;//後向指針賦值 this.prev = prev;//前向指針賦值 } }
2>LinkedList 的關鍵源碼
//LinedList繼承了AbstractSequentialList,支持泛型 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() { } //按c裏面的元素生成一個LinkedList public LinkedList(Collection<? extends E> c) { this();//調用空的構造函數 addAll(c);//將c裏面的元素添加到空鏈表尾部 } //首部增長結點,結點的值爲e private void linkFirst(E e) { final Node<E> f = first;//f指向頭結點 //生成一個新結點,結點的值爲e,其前向指針爲null,後向指針爲f final Node<E> newNode = new Node<>(null, e, f); //first指向新生成的結點,f保存着老的頭結點信息 first = newNode; if (f == null) //若是f爲null,則表示整個鏈表目前是空的,則尾結點也指向新結點 last = newNode; else //f(老的頭結點)的前向指針指向最新的結點信息 f.prev = newNode; size++;//元素個數+1. modCount++;//修改次數+1 } //尾部增長結點,結點的值爲e void linkLast(E e) { final Node<E> l = last;//l指向尾結點 //生成一個新結點,結點的值爲e,其前向指針爲l,後向指針爲null final Node<E> newNode = new Node<>(l, e, null); //last指向新生成的結點,l保存着老的尾結點信息 last = newNode; if (l == null) //若是l爲null,則表示整個鏈表目前是空的,則頭結點也指向新結點 first = newNode; else //l(老的尾結點)的後向指針指向最新的結點信息 l.next = newNode; size++;//元素個數+1 modCount++;//修改次數+1 } //非空結點succ以前插入新結點,新結點的值爲e void linkBefore(E e, Node<E> succ) { // assert succ != null;//外界調用需保證succ不爲null,不然程序會拋出空指針異常 final Node<E> pred = succ.prev;//pred指向succ的前向結點 //生成一個新結點,結點的值爲e,其前向指針指向pred,後向指針指向succ final Node<E> newNode = new Node<>(pred, e, succ); succ.prev = newNode;//succ的前向指針指向newNode if (pred == null) //若是pred爲null,則表示succ爲頭結點,此時頭結點指向最新生成的結點newNode first = newNode; else //pred的後向指針指向新生成的結點,此時已經完成告終點的插入操做 pred.next = newNode; size++;//元素個數+1 modCount++;//修改次數+1 } //刪除頭結點,並返回該結點的值 private E unlinkFirst(Node<E> f) { // assert f == first && f != null;//需確保f爲頭結點,且鏈表不爲Null final E element = f.item;//得到結點的值 final Node<E> next = f.next;//next指向f的後向結點 f.item = null;//釋放數據結點 f.next = null;//釋放f的後向指針 first = next;//first指向f的後向結點 if (next == null) //若是next爲null,則表示f爲last結點,此時鏈表即爲空鏈表 last = null; else //修改next的前向指針,由於first結點的前向指針爲null next.prev = null; size--;//元素個數-1 modCount++;//修改次數+1 return element; } //刪除尾結點,並返回尾結點的內容 private E unlinkLast(Node<E> l) { // assert l == last && l != null;//需確保l爲尾結點,且鏈表不爲null final E element = l.item;//得到結點的值 final Node<E> prev = l.prev;//prev執行l的前向結點 l.item = null;//釋放l結點的值 l.prev = null; //釋放l結點的前向指針 last = prev;//last結點指向l的前向結點 if (prev == null) //若是prev爲null,則表示l爲first結點,此時鏈表即爲空鏈表 first = null; else //修改prev的後向指針,由於last結點的後向指針爲null prev.next = null; size--;//元素個數-1 modCount++;//修改次數+1 return element; } //刪除結點x E unlink(Node<E> x) { // assert x != null;//需確保x不爲null,不然後續操做會拋出空指針異常 final E element = x.item;//保存x結點的值 final Node<E> next = x.next;//next指向x的後向結點 final Node<E> prev = x.prev;//prev指向x的前向結點 if (prev == null) { //若是prev爲空,則x結點爲first結點,此時first結點指向next結點(x的後向結點) first = next; } else { prev.next = next;//x的前向結點的後向指針指向x的後向結點 x.prev = null;//釋放x的前向指針 } if (next == null) { //若是next結點爲空,則x結點爲尾部結點,此時last結點指向prev結點(x的前向結點) last = prev; } else { next.prev = prev;//x的後向結點的前向指針指向x的前向結點 x.next = null;//釋放x的後向指針 } x.item = null;//釋放x的值節點,此時x節點能夠徹底被GC回收 size--;//元素個數-1 modCount++;//修改次數+1 return element; } //得到頭結點的值 public E getFirst() { final Node<E> f = first;//f指向first結點 if (f == null)//此時鏈表爲空 throw new NoSuchElementException(); return f.item;//返回first結點的值 } //得到尾結點的值 public E getLast() { final Node<E> l = last;//l指向last結點 if (l == null)//此時鏈表爲空 throw new NoSuchElementException(); return l.item;//返回last結點的值 } //移除頭結點 public E removeFirst() { final Node<E> f = first;//得到頭結點 if (f == null)//此時鏈表爲空 throw new NoSuchElementException(); return unlinkFirst(f);//摘除頭結點 } //移除尾結點 public E removeLast() { final Node<E> l = last;//得到尾結點 if (l == null)//此時鏈表爲空 throw new NoSuchElementException(); return unlinkLast(l);//摘除尾結點 } //添加到頭結點,結點的值爲e public void addFirst(E e) { linkFirst(e);//添加到頭部 } //添加到尾結點,結點值爲e public void addLast(E e) { linkLast(e);//添加到尾部 } //判斷元素(值爲o)是o否在鏈表中 public boolean contains(Object o) { return indexOf(o) != -1;//定位元素 } //返回元素個數 public int size() { return size; } //添加元素,元素值爲e public boolean add(E e) { linkLast(e);//添加到鏈表尾部 return true; } //移除值爲o的元素,o能夠爲null,找到一個刪除即返回 public boolean remove(Object o) { if (o == null) {//元素爲null for (Node<E> x = first; x != null; x = x.next) {//從頭結點開始遍歷 if (x.item == null) {//找到一個結點 unlink(x);//刪除元素 return true; } } } else {//元素不爲空 for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; } //將c中的元素都添加到當前鏈表中 public boolean addAll(Collection<? extends E> c) { return addAll(size, c);//添加到鏈表尾部 } //第序號爲index處,添加c中全部的元素到當前鏈表中(後向添加的) public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index);//判斷index是否超出界 Object[] a = c.toArray();//將集合轉換爲數組 int numNew = a.length; if (numNew == 0) return false; Node<E> pred, succ; if (index == size) {//若是index爲元素個數,即第index個結點爲尾結點 succ = null; pred = last;//指向爲結點 } else { succ = node(index);//succ指向第index個結點 pred = succ.prev;//pred指向succ的前向結點 } //for循環結束後,a裏面的元素都添加到當前鏈表裏面了,後向添加 for (Object o : a) { @SuppressWarnings(