java.util.LinkedListjava
有,就是LinkedList。LinkedList實現的接口以下,其實也能夠當作stack使用:node
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
Deque
是一個雙端隊列的接口,而Deque又繼承了接口Queue
。因此LinkedList能夠做爲隊列、雙端隊列來使用。數組
AbstractSequentialList
提供了順序訪問的方法,固然,大部分方法都依賴於ListIterator來實現,因此將鍋甩給了子類。性能
一樣很簡單,是一個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; } }
有屬性first和last記錄着鏈表的開始和結束節點。this
在LinkedList中,大量的方法須要先得到指定下標的節點,具體實現以下:code
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; } }
能夠看出,開發者已經盡力優化,根據index大小決定從何處開始遍歷。繼承
遍歷方法利用了鏈表結構的特性,進行遍歷。其中有以下屬性記錄遍歷狀態。接口
private Node<E> lastReturned; //記錄最近一次返回的節點 private Node<E> next; //記錄下一個要返回的節點 private int nextIndex; //記錄下一個要返回的位置 private int expectedModCount = modCount; //記錄指望的修改次數
LinkedList每次劃分,不是採用的1/2策略,而是每次分裂出來的一塊數據都增長一個BATCH_UNIT(1024)
的大小。比較有趣的是,每次分裂出來的Spliterator並非LinkedList本身實現的Spliterator,而是一個ArraySpliterator,ArraySpliterator採用的是1/2的分裂策略。因此LinkedList每次分裂都想盡量快的分裂出更多的元素,而且分裂過程當中將鏈表結構轉化爲數組結構,這樣作多是出於性能的考慮,具體什麼緣由仍是比較納悶的。隊列
//該方法位於class LLSpliterator中 public Spliterator<E> trySplit() { Node<E> p; int s = getEst(); if (s > 1 && (p = current) != null) { int n = batch + BATCH_UNIT; if (n > s) n = s; if (n > MAX_BATCH) n = MAX_BATCH; //copy到數組中 Object[] a = new Object[n]; int j = 0; do { a[j++] = p.item; } while ((p = p.next) != null && j < n); current = p; batch = j; est = s - j; //這裏返回的不是LLSpliterator,實際上是ArraySpliterator return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED); } return null; }