Java ArrayDeque源碼學習

public class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>, Cloneable, Serializable 1.6

雙端隊列的動態(tài)數(shù)組實現(xiàn)
This class is likely to be faster than when used as a stack, and faster than LinkedList when used as a queue.

  1. 數(shù)組大小分配算法
    2 ^ n <= numElements < 2 ^ (n+1) 分配 2 ^ (n+1)大小铃在。
    最少分配8,最多分配2 ^ 30個元素碍遍。

        /**
         * The minimum capacity that we'll use for a newly created deque.
         * Must be a power of 2.
         */
        private static final int MIN_INITIAL_CAPACITY = 8;
    
        // ******  Array allocation and resizing utilities ******
    
        private static int calculateSize(int numElements) {
            int initialCapacity = MIN_INITIAL_CAPACITY;
            // Find the best power of two to hold elements.
            // Tests "<=" because arrays aren't kept full.
            if (numElements >= initialCapacity) {
                initialCapacity = numElements;
                initialCapacity |= (initialCapacity >>>  1); //前2位為1
                initialCapacity |= (initialCapacity >>>  2); //前4位為1
                initialCapacity |= (initialCapacity >>>  4); //前8位為1
                initialCapacity |= (initialCapacity >>>  8); //前16位為1
                initialCapacity |= (initialCapacity >>> 16); //前32位為1
                initialCapacity++; //進1位
                if (initialCapacity < 0)   // Too many elements, must back off
                    initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
            }
            return initialCapacity;
        }
    
  2. 容量擴充怕敬,加倍操作

    /**
     * Doubles the capacity of this deque.  Call only when full, i.e.,
     * when head and tail have wrapped around to become equal.
     */
    private void doubleCapacity() {
        assert head == tail;//相同位置东跪,說明數(shù)組已滿
        int p = head;
        int n = elements.length;
        int r = n - p; // number of elements to the right of p
        int newCapacity = n << 1;
        if (newCapacity < 0)
            throw new IllegalStateException("Sorry, deque too big");
        Object[] a = new Object[newCapacity];
        System.arraycopy(elements, p, a, 0, r);
        System.arraycopy(elements, 0, a, r, p);
        elements = a;
        head = 0;
        tail = n;
    }
    ```   ?
    
  3. 移動 機智的&操作
    index & (elements.length - 1) 從0開始到最后一位,然后回到第0位虽填。
    (index+elements.length) % elements.length 取模也可以丁恭,性能不如位運算;

    public void addFirst(E e) {
         if (e == null)
         throw new NullPointerException();
         elements[head = (head - 1) & (elements.length - 1)] = e;
         if (head == tail)
           doubleCapacity();
    }
    public void addLast(E e) {
        if (e == null)
            throw new NullPointerException();
        elements[tail] = e;
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
            doubleCapacity();//空間滿了斋日,加倍
    }
    
    public E pollLast() {
        int t = (tail - 1) & (elements.length - 1);
        @SuppressWarnings("unchecked")
        E result = (E) elements[t];
        if (result == null)
            return null;
        elements[t] = null;
        tail = t;
        return result;
    }
    

    size

    public int size() {
        return (tail - head) & (elements.length - 1);//-3與7牲览,剛好是8減3
    }
    
  4. 刪除操作,刪除中間某個節(jié)點需要數(shù)組的移動桑驱。 有意思
    如果刪除節(jié)點靠近頭結點,則移動前半部分跛蛋,返回false熬的;
    如果刪除節(jié)點靠近尾結點,則移動后半部分赊级,返回true押框;-> 實現(xiàn)最少的數(shù)組移動

    private boolean delete(int i) {
        checkInvariants();
        final Object[] elements = this.elements;
        final int mask = elements.length - 1;
        final int h = head;
        final int t = tail;
        final int front = (i - h) & mask;
        final int back  = (t - i) & mask;
    
        // Invariant: head <= i < tail mod circularity
        if (front >= ((t - h) & mask))
            throw new ConcurrentModificationException();
    
        // Optimize for least element motion
        if (front < back) {//刪除節(jié)點靠近頭結點
            if (h <= i) { //刪除節(jié)點在頭結點后邊,將front部分后移即可
                System.arraycopy(elements, h, elements, h + 1, front);
            } else { // 刪除節(jié)點在頭結點前邊理逊,分段處理
                System.arraycopy(elements, 0, elements, 1, i);
                elements[0] = elements[mask];
                System.arraycopy(elements, h, elements, h + 1, mask - h);
            }
            elements[h] = null;
            head = (h + 1) & mask;
            return false;
        } else {//刪除節(jié)點靠近尾結點
            if (i < t) { // Copy the null tail as well
                System.arraycopy(elements, i + 1, elements, i, back);
                tail = t - 1;
            } else { // Wrap around
                System.arraycopy(elements, i + 1, elements, i, mask - i);
                elements[mask] = elements[0];
                System.arraycopy(elements, 1, elements, 0, t);
                tail = (t - 1) & mask;
            }
            return true;
        }
    }
    

    ArrayDeque并不提供index訪問晋被,所以此函數(shù)只用于removeFirstOccurrence或者Iterator.remove


@夢工廠2018.3.10

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肋联,隨后出現(xiàn)的幾起案子橄仍,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異罗岖,居然都是意外死亡,警方通過查閱死者的電腦和手機哑了,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門拆火,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人模狭,你說我怎么就攤上這事邪意⊙缡鳎” “怎么了又憨?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵零如,是天一觀的道長考蕾。 經常有香客問我蚯窥,道長葵姥,這世上最難降的妖魔是什么颊咬? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任态辛,我火速辦了婚禮,結果婚禮上馁害,老公的妹妹穿的比我還像新娘限寞。我一直安慰自己计雌,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鹃祖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪祖能。 梳的紋絲不亂的頭發(fā)上蛾洛,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天鳞滨,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛哀墓,可吹牛的內容都是我干的吠各。 我是一名探鬼主播纵散,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盐碱,長吁一口氣:“原來是場噩夢啊……” “哼趣倾!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡到推,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年唧喉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片楼入。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡愧薛,死狀恐怖碘箍,靈堂內的尸體忽然破棺而出货邓,到底是詐尸還是另有隱情四濒,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站仆邓,受9級特大地震影響搞疗,放射性物質發(fā)生泄漏。R本人自食惡果不足惜业簿,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一钝腺、第九天 我趴在偏房一處隱蔽的房頂上張望诲侮。 院中可真熱鬧镀虐,春花似錦、人聲如沸沟绪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绽慈。三九已至诺核,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間久信,已是汗流浹背窖杀。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留裙士,地道東北人入客。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親桌硫。 傳聞我的和親對象是個殘疾皇子夭咬,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容