天天看點

Queue與Deque的差別

一, 引言:

在研究java集合源碼的時候,發現了一個很少用但是很有趣的點:Queue以及Deque;

平常在寫leetcode經常用LinkedList向上轉型Deque作為棧或者隊列使用,但是一直都不知道Queue的作用,于是就直接官方文檔好了。

二,Queue和Deque:

1,Deque是Queue的子接口;

從源碼中可以得知:Queue以及Deque都是繼承于Collection,Deque是Queue的子接口。

public interface Deque<E> extends Queue<E> {}
           

2,Queue——單端隊列;Deque——雙端隊列;

從Deque的解釋中,我們可以得知:Deque是double ended queue,我将其了解成雙端隊列,就是可以在首和尾都進行插入或删除元素。

而Queue的解釋中,Queue就是簡單的FIFO(先進先出)隊列。是以在概念上來說,Queue是FIFO的單端隊列,Deque是雙端隊列。​​​​​​​

3,Queue常用子類——PriorityQueue;Deque常用子類——LinkedList以及ArrayDeque;

Queue有一個直接子類PriorityQueue。

而Deque中直接子類有兩個:LinkedList以及ArrayDeque。

三,PriorityQueue:

Queue與Deque的差別

我覺得重點就在圈定的兩個單詞:無邊界的,優先級的堆。

從源碼中,明顯看到PriorityQueue的底層資料結構是數組,而無邊界的形容,那麼指明了PriorityQueue是自帶擴容機制的,具體請看PriorityQueue的grow方法。 

四,LinkedList以及ArrayDeque:

Queue與Deque的差別

從官方解釋來看,ArrayDeque是無初始容量的雙端隊列,LinkedList則是雙向連結清單。

而我們還能看到,ArrayDeque作為隊列時的效率比LinkedList要高。

而在棧的使用場景下,無疑具有尾結點,不需判空的LinkedList更為高效。

示範ArrayDeque作為隊列以及LinkedList作為棧的使用:

private static void usingAsQueue() {
        Deque<Integer> queue=new ArrayDeque<>();

        System.out.println("隊列為空:"+queue.isEmpty());   //判斷隊列是否為空

        queue.addLast(12);   //添加元素
        System.out.println(queue.peekFirst());   //擷取隊列首部元素
        System.out.println(queue.pollFirst());   //擷取并移除棧頂元素

 }

private static void usingAsStack() {
        //作為棧使用
        Deque<Integer> stack=new LinkedList<>();

        System.out.println("棧為空:"+stack.isEmpty());   //判斷棧是否為空

        stack.addFirst(12);//添加元素
        System.out.println(stack.peekFirst());   //擷取棧頂元素
        System.out.println(stack.pollFirst());   //擷取并移除棧頂元素
    }
           

小提示: 

在Deque中,擷取并移除元素的方法有兩個,分别是removeXxx以及peekXxx。

存在元素時,兩者的處理都是一樣的。

但是當Deque内為空時,removeXxx會直接抛出NoSuchElementException,

而peekXxx則會傳回null。

是以無論在實際開發或者算法時,推薦使用peekXxx方法。

其實ArrayDeque和LinkedList都可以作為棧以及隊列使用,但是從執行效率來說,ArrayDeque作為隊列,以及LinkedList作為棧使用,會是更好的選擇。

五,小結:

  • PriorityQueue可以作為堆使用,而且可以根據傳入的Comparator實作大小的調整,會是一個很好的選擇。
  • ArrayDeque可以作為棧或隊列使用,但是棧的效率不如LinkedList高,通常作為隊列使用。
  • LinkedList可以作為棧或隊列使用,但是隊列的效率不如ArrayQueue高,通常作為棧使用。

六,Queue和Deque的方法差別:

在java中,Queue被定義成單端隊列使用,Deque被定義成雙端隊列使用。

而由于雙端隊列的定義,Deque可以作為棧或者隊列使用;

而Queue隻能作為隊列或者依賴于子類的實作作為堆使用。

方法上的差別如下:

Queue Deque
add addFirst
offer offerFirst
remove removeFirst
poll pollFirst
element getFirst
peek peekFirst

繼續閱讀