一, 引言:
在研究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:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbwxCdh1mcvZ2LcV2Zh1Wa9M3clN2byBXLzN3btg3P3pVdC5GT5FEVOFTQE1kMJR1T3tGVNdXS6xEd5ITW110MZVnVYVGc4dVW1NWbiBHcXFGbKdFT150VMpnTzIWdjJjYzp0VMVXOyIGMKhVWqlTeMZTTINGMShUYvwlbj5yZtlmbkN3YuQnclZnbvN2Ztl2Lc9CX6MHc0RHaiojIsJye.jpg)
我覺得重點就在圈定的兩個單詞:無邊界的,優先級的堆。
從源碼中,明顯看到PriorityQueue的底層資料結構是數組,而無邊界的形容,那麼指明了PriorityQueue是自帶擴容機制的,具體請看PriorityQueue的grow方法。
四,LinkedList以及ArrayDeque:
從官方解釋來看,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 |