LinkedList是一個雙向鏈表的數據結構實現。java
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
這個類提供了一個List接口實現,爲實現序列訪問的數據存儲結構提供了所須要的最小化接口實現。對於支持隨機訪問數據的List好比數組,應該優先使用AbstractList。node
一個有序的集合。這個接口能夠精確控制每一個元素在列表中的位置插入。用戶能夠經過整數索引來訪問元素(位置在列表中)。數組
一個有序的集合支持在頭和尾進行插入和刪除元素。deque是 double ended queue (雙端隊列)的縮寫。
deque的大多實現元素數量是沒有大小限制的。但這個接口支持容量限制。微信
public LinkedList() { } public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
第一個是一個空的構造器,第二個構造器調用了addAll()方法。數據結構
在研究addAll()方法以前,咱們先來看一下幾個重要的屬性。源碼分析
//容器的大小: transient int size = 0; //首節點: transient Node<E> first; //尾節點: transient Node<E> last; //節點數據結構 private static class Node<E> { E item;//節點的值 Node<E> next;//節點的下一個節點 若是等於null 則爲尾節點 Node<E> prev;//節點的上一個節點,若是等於null則爲首節點 Node(Node<E> prev, E element, Node<E> next) {//構造器 構造節點 this.item = element; this.next = next; this.prev = prev; } }
private void linkFirst(E e) { final Node<E> f = first;//得到第一個節點 final Node<E> newNode = new Node<>(null, e, f);//構造本次插入的首節點,以前的首節點做爲下一個節點 first = newNode;//本次插入節點做爲首節點 if (f == null)//若是首節點爲空,則尾節點也爲他 last = newNode; else f.prev = newNode;//不然,以前的首節點做爲新節點的下一個節點 size++;//容器大小加一 modCount++;//修改次數加一 }
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++;//修改次數加一 }
//插入節點e ,在不爲空的succ節點以前 void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev;//succ的前一個節點 final Node<E> newNode = new Node<>(pred, e, succ);//構造新節點插入succ以前 succ.prev = newNode;//succ的前一個節點爲新構造的節點 if (pred == null)//若是succ的前一個節點爲空,則本次插入節點將作爲首節點 first = newNode; else pred.next = newNode;//不然新節點做爲succ的上一個節點 size++;//容器大小加一 modCount++;//修改次數加一 }
private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; }
f.next 釋放了內存,等待垃圾回收機制進行回收內存。this
//unlinkFirst方法被調用移除首節點 public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); }
private E unlinkLast(Node<E> l) { // assert l == last && l != null; final E element = l.item; final Node<E> prev = l.prev; l.item = null; l.prev = null; // help GC last = prev; if (prev == null) first = null; else prev.next = null; size--; modCount++; return element; } public E removeLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(l); }
public E getFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return f.item; }
public boolean remove(Object o) { if (o == 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; }
public E peek() { final Node<E> f = first; return (f == null) ? null : f.item; }
public E poll() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); }
public boolean offer(E e) { return add(e); }
從poll和offer方法能夠看出Linked是一個FIFO先進先出隊列(first input first output )spa
//使用二分法用索引查找元素 Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; }
}code
關注個人公衆號第一時間閱讀有趣的技術故事
掃碼關注:
也能夠在微信搜索公衆號便可關注我:codexiulian
渴望與你一塊兒成長進步!繼承