Java容器類研究5:LinkedList

java.util.LinkedListjava

Java中有現成的隊列能夠用嗎

有,就是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來實現,因此將鍋甩給了子類。性能

LinkedList用什麼結構來實現

一樣很簡單,是一個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大小決定從何處開始遍歷。繼承

LinkedList實現了本身的ListIterator

遍歷方法利用了鏈表結構的特性,進行遍歷。其中有以下屬性記錄遍歷狀態。接口

private Node<E> lastReturned; //記錄最近一次返回的節點
    private Node<E> next;    //記錄下一個要返回的節點
    private int nextIndex;   //記錄下一個要返回的位置
    private int expectedModCount = modCount;  //記錄指望的修改次數

LinkedList的Spliterator採用什麼樣的分割策略

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;
        }
相關文章
相關標籤/搜索