java.util.ArrayDeque循環(huán)隊列源碼(jdk1.7)

準備知識

因為ArrayDeque使用了循環(huán)隊列,所以首先要了解循環(huán)隊列數(shù)據(jù)結構的原理。
http://www.reibang.com/p/5fa1d2234045

屬性

    // 存儲E類型元素的數(shù)組  
    private transient E[] elements;  
  
    // 循環(huán)隊列的頭元素索引  
    private transient int head;  
  
    // 循環(huán)隊列的尾元素索引   
    private transient int tail;  
  
    // 循環(huán)隊列的初始化最小容量為8   
    private static final int MIN_INITIAL_CAPACITY = 8;  

構造方法

    // 構造一個空的數(shù)組循環(huán)隊列冕房,初始化Object數(shù)組長度為16  
    public ArrayDeque() {  
        elements = (E[]) new Object[16];  
    }  
    // 構造一個指定長度的數(shù)組循環(huán)隊列
    public ArrayDeque(int numElements) {  
        allocateElements(numElements);  
    }  
  
    // 分配指定元素長度的Object數(shù)組  
    private void allocateElements(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);  
            initialCapacity |= (initialCapacity >>>  2);  
            initialCapacity |= (initialCapacity >>>  4);  
            initialCapacity |= (initialCapacity >>>  8);  
            initialCapacity |= (initialCapacity >>> 16);  
            initialCapacity++;  
  
            if (initialCapacity < 0)   // Too many elements, must back off  
                initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements  
        }  
        elements = (E[]) new Object[initialCapacity];  
    }  
    // 構造一個包含指定 collection 的元素的循環(huán)隊列
    public ArrayDeque(Collection<? extends E> c) {  
        // 先分配集合c那么長的空間  
        allocateElements(c.size());  
        // 將c中的元素插入到雙端隊列中  
        addAll(c);  
    }  
      
    /**  
     * 插入集合c中的所有元素躏啰,設置標記位modified代表是否插入元素。  
     * 如果插入元素了就返回標記位為true耙册。  
     */  
    public boolean addAll(Collection<? extends E> c) {  
        boolean modified = false;  
        for (E e : c)  
            if (add(e))  
                modified = true;  
        return modified;  
    }  
      
    // 在隊列的尾部插入元素e  
    public boolean add(E e) {  
        addLast(e);  
        return true;  
    }  
  
    public void addLast(E e) {  
        // 如果插入的元素為空给僵,那么就拋出空指針異常  
        if (e == null)  
            throw new NullPointerException();  
        // 在隊列的尾部插入元素  
        elements[tail] = e;  
        /**  
         * 按照循環(huán)隊列的特點,隊滿時采用(tail+1)%elements.length==head,而在此處使用了與位運算來代替取余運算详拙,由于位運算速度快帝际,所以這種方式效率高。  
         * 而此處代碼的意思是如果循環(huán)隊列已經達到了隊滿的狀態(tài)饶辙,那么就進行擴容操作蹲诀、并且賦值。  
         */  
        if ( (tail = (tail + 1) & (elements.length - 1)) == head)  
            doubleCapacity();  
    }  
      
    // 將隊列擴充原來的2倍弃揽,并且將元素復制到擴充的數(shù)組中脯爪。
    private void doubleCapacity() {  
        assert head == tail;  
        // 設置暫時變量p,如果直接操作head矿微,那么就會修改head痕慢。而本意是操作head而不修改head。  
        int p = head;  
        int n = elements.length;  
        // head右邊元素的個數(shù)  
        int r = n - p; // number of elements to the right of p  
        // 設置新容量涌矢,左移一位就相當于擴充為原來的2倍掖举。  
        int newCapacity = n << 1;  
        // 如果新容量的小于0,那么就會拋出非法狀態(tài)異常。  
        if (newCapacity < 0)  
            throw new IllegalStateException("Sorry, deque too big");  
        // 創(chuàng)建新容量的Object數(shù)組  
        Object[] a = new Object[newCapacity];  
        // 將elements元素復制到數(shù)組a中蒿辙,從elements數(shù)組的p開始拇泛,數(shù)組a從0開始,復制的長度為r  
        System.arraycopy(elements, p, a, 0, r);  
        // 將elements元素復制到數(shù)組a中思灌,從elements數(shù)組的0開始俺叭,數(shù)組a從r開始,復制的長度為p  
        System.arraycopy(elements, 0, a, r, p);  
        // 將新數(shù)組a賦值給elements  
        elements = (E[])a;  
        // 然后設置新數(shù)組的頭索引為0.尾索引為n  
        head = 0;  
        tail = n;  
    }  

方法

addFirst方法:在隊列的頭部插入元素e泰偿。

    public void addFirst(E e) {  
        // 如果插入元素為空熄守,那么就拋出空指針異常  
        if (e == null)  
            throw new NullPointerException();  
        // 與位運算代替取余運算,計算出新的頭索引的值耗跛,進行插入元素e  
        elements[head = (head - 1) & (elements.length - 1)] = e;  
        // 如果頭索引和尾索引重合裕照,達到了循環(huán)隊列的隊滿狀態(tài),就進行擴容賦值操作  
        if (head == tail)  
            doubleCapacity();  
    }  

remove方法:獲取并移除此雙端隊列所表示的隊列的頭调塌。

    public E remove() {  
        return removeFirst();  
    }  
  
    /**  
     * @throws NoSuchElementException {@inheritDoc}  
     */  
    public E removeFirst() {  
        E x = pollFirst();  
        if (x == null)  
            throw new NoSuchElementException();  
        return x;  
    }  
      
    public E pollFirst() {  
        int h = head;  
        E result = elements[h];  
        // 如果頭索引下標對應的元素為空晋南,那么就返回空  
        if (result == null)  
            return null;  
        // 將頭索引處的元素設置為空  
        elements[h] = null;  
        // 將頭索引對應的空元素,與運算計算出新的索引值  
        head = (h + 1) & (elements.length - 1);  
        return result;  
    }  

總結

1. ArrayDeque采用循環(huán)隊列數(shù)據(jù)結構設計的羔砾。(所以增加负间、刪除偶妖、判斷隊空、判斷隊滿都是循環(huán)隊列的套路)
2. ArrayDeque增加元素政溃,如果循環(huán)隊列容量不夠趾访,那么就擴容為原來的2倍。
3. ArrayDeque采用與位運算來代替求余運算董虱,提高了效率扼鞋。(用在判斷隊滿的時候)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市愤诱,隨后出現(xiàn)的幾起案子云头,更是在濱河造成了極大的恐慌,老刑警劉巖转锈,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盘寡,死亡現(xiàn)場離奇詭異,居然都是意外死亡撮慨,警方通過查閱死者的電腦和手機竿痰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砌溺,“玉大人影涉,你說我怎么就攤上這事」娣ィ” “怎么了蟹倾?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長猖闪。 經常有香客問我鲜棠,道長,這世上最難降的妖魔是什么培慌? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任豁陆,我火速辦了婚禮,結果婚禮上吵护,老公的妹妹穿的比我還像新娘盒音。我一直安慰自己,他們只是感情好馅而,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布祥诽。 她就那樣靜靜地躺著,像睡著了一般瓮恭。 火紅的嫁衣襯著肌膚如雪雄坪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天屯蹦,我揣著相機與錄音诸衔,去河邊找鬼盯漂。 笑死,一個胖子當著我的面吹牛笨农,可吹牛的內容都是我干的。 我是一名探鬼主播帖渠,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼谒亦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了空郊?” 一聲冷哼從身側響起份招,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狞甚,沒想到半個月后锁摔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡哼审,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年谐腰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩盾。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡十气,死狀恐怖,靈堂內的尸體忽然破棺而出春霍,到底是詐尸還是另有隱情砸西,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布址儒,位于F島的核電站芹枷,受9級特大地震影響,放射性物質發(fā)生泄漏莲趣。R本人自食惡果不足惜鸳慈,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望妖爷。 院中可真熱鬧蝶涩,春花似錦、人聲如沸絮识。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽次舌。三九已至熄攘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彼念,已是汗流浹背挪圾。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工浅萧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哲思。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓洼畅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棚赔。 傳聞我的和親對象是個殘疾皇子帝簇,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容

  • 學生時代的我們,在一起聚會談論的話題都是關于學習靠益、夢想丧肴;然而現(xiàn)在的我們,談論的都是事業(yè)胧后、婚姻芋浮!是我們長大了還是我們...
    獨立自主的niki閱讀 248評論 0 0
  • 萬能的朋友圈,你們聽說過這個品牌嘛壳快? 昨天在火車上偶遇一個姐纸巷,聽她給對面的一個小姑娘講這個品牌,出于好奇濒憋,再加上火...
    慕星讀者OR獨者閱讀 649評論 0 1
  • 正值初春 現(xiàn)已夜深 昏黃街頭 空無一人 手持美酒 思他已久 一痛而飲 思念難憶 酒不香醇 欠你溫存 孤樹零零 兩淚涕零
    南方阿球閱讀 146評論 0 0
  • A 歷史總是驚人的的相似何暇。去年此門中,今年亦如是凛驮。 因為工作的關系裆站,最近十多年,每年都會來一兩次嘉峪關黔夭。今年巧了宏胯,...
    小溪流_3f91閱讀 895評論 21 24