Queue
Queue隊列介紹
Queue是用於模擬隊列的,啥叫隊列?隊列就是排隊的意思,比如排隊結賬,先進入隊伍中,先排到先付賬走人;后排到的,進入隊伍,等前面的人出隊伍后,再跟在后面付錢出隊。符合“先進先出FIFO”的規則,是一種線性表。插入在一端,刪除則在另一端。入隊(offer)在隊尾,出隊(poll)在隊頭。
Queue接口有實現類PriorityQueue,有另一個雙端隊列接口Deque。
Queue隊列進出示意圖

Queue常用方法
PriorityQueue擁有Queue和Collection的方法。下面主要介紹一些常用方法:
boolean add(E e);:將指定元素加入到隊列的尾部。E element();:獲取隊列頭部的元素,但是不刪除該元素。boolean offer(E e);:將指定元素加入到隊列的尾部。E peek();:獲取隊列頭部的元素,但是不刪除元素;若隊列為空,返回null。E poll();:獲取隊列頭部的元素,並刪除該元素。若隊列為空,返回null。E remove();:獲取隊列頭部的元素,並刪除該元素。若隊列為空,拋異常。
PriorityQueue
PriorityQueue概述
PriorityQueue是Queue隊列實現類,PriorityQueue保存隊列元素的順序不是按照加入隊列的順序,而是按照隊列元素的大小進行重新排序。當調用peek()或者poll()方法獲取隊列元素時,獲取的是隊列最小元素,而不是先入隊列的元素。有點反先入先出規則。
PriorityQueue示例
1)運行主類:
public class DemoApplication {
public static void main(String[] args) {
PriorityQueue priorityQueue = new PriorityQueue();
priorityQueue.offer(5);
priorityQueue.offer(-1);
priorityQueue.offer(3);
priorityQueue.offer(7);
//查看入隊順序
System.out.println("隊列輸出:" + priorityQueue);
//peek方法獲取隊頭元素但是不刪除元素
System.out.println("peek()方法獲取隊頭:" + priorityQueue.peek());
//查看第一個元素即為最小元素
System.out.println("第一個隊列元素出隊:" + priorityQueue.poll());
System.out.println("第二個隊列元素出隊:" + priorityQueue.poll());
System.out.println("第三個隊列元素出隊:" + priorityQueue.poll());
System.out.println("第四個隊列元素出隊:" + priorityQueue.poll());
System.out.println("null隊列:" + priorityQueue.poll());
}
}
2)運行結果:
隊列輸出:[-1, 5, 3, 7]
peek()方法獲取隊頭:-1
第一個隊列元素出隊:-1
第二個隊列元素出隊:3
第三個隊列元素出隊:5
第四個隊列元素出隊:7
null隊列:null
Deque
Deque雙端隊列介紹
Deque是Queue子接口,是雙端隊列。可以同時從兩端(隊列頭部和尾部)添加、刪除元素。所以可以用來實現棧的數據結構。有兩個實現類(ArrayDeque和LinkedList)
Deque常用方法
void addFirst(E e):將指定元素插入該雙端隊列的頭部,比較重要,下面很多方法頭部插入內部實現都是通過這個來實現的,如offerFirst()。void addLast(E e):將指定元素插入該雙端隊列的尾部。比較重要,下面添加到尾部插入內部實現都是通過這個來實現的,如offerLast()。E getFirst():獲取但不刪除雙端隊列的第一個元素。E getLast():獲取但不刪除雙端隊列的最后一個元素。E removeFirst():獲取並刪除該雙端隊列的第一個元素。棧的出隊列方法pop()也是通過該方法實現的。E removeLast():獲取並刪除該雙端隊列的最后一個元素。Iterator<E> descendingIterator():返回雙端隊列的迭代器,逆向順序迭代元素。boolean offerFirst(E e):將指定元素插入該雙端隊列的頭部。
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
boolean offerLast(E e):將指定元素插入該雙端隊列的尾部。
public boolean offerLast(E e) {
addLast(e);
return true;
}
E peekFirst():獲取但不刪除該雙端隊列的第一個元素;若隊列為空,則返回null。
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
E peekLast():獲取但不刪除該雙端隊列的最后一個元素;若隊列為空,則返回null。
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
E pollFirst():獲取並刪除該雙端隊列的第一個元素;若隊列為空,則返回null。
public E pollFirst() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}
E pollLast():獲取並刪除該雙端隊列的最后一個元素;若隊列為空,則返回null。
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
E pop():棧方法,pop出該雙端隊列表示棧的棧頂元素,等價於removeFirst()方法。
public E pop() {
return removeFirst();
}
void push(E e):棧方法,push元素進入該雙端隊列表示棧的棧頂,等價於addFist()方法。
public void push(E e) {
addFirst(e);
}
boolean removeFirstOccurrence(Object o):刪除該雙端隊列的第一次出現的元素o,底層通過remove()方法實現。
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
boolean removeLastOccurrence(Object o):刪除該涮短隊列的最后一次出現的元素o。
ArrayDeque
ArrayDeque概述
ArrayDeque底層實現類似於ArrayList,都是通過動態、可分配的Object[]數組來實現元素存儲,當集合元素超過數組容量,會重新分配一個新的數組來存儲集合元素。
ArrayDeque示例
1)運行主類
public class DemoApplication {
public static void main(String[] args) {
//可以作為棧來使用,先進后出
ArrayDeque<String> arrayDeque = new ArrayDeque<>();
arrayDeque.push("book01");
arrayDeque.push("book03");
arrayDeque.push("book02");
arrayDeque.push("book04");
System.out.println("原棧:" + arrayDeque);
System.out.println("獲取頭部元素,但不刪除該元素,peek(): " + arrayDeque.peek());
System.out.println("獲取頭部元素,且刪除該元素,pop(): " +arrayDeque.pop());
System.out.println("獲取第一個元素,但不刪除:" + arrayDeque.getFirst());
System.out.println("獲取最后一個元素,但不刪除:" + arrayDeque.getLast());
System.out.println("在雙端隊列頭部插入元素:" + arrayDeque.offerFirst("booknew01"));
System.out.println("在雙端隊列尾部插入元素:" + arrayDeque.offerLast("booknew02"));
System.out.println("新棧:" + arrayDeque);
}
}
2)運行結果
原棧:[book04, book02, book03, book01]
獲取頭部元素,但不刪除該元素: book04
獲取頭部元素,且刪除該元素: book04
獲取第一個元素,但不刪除:book02
獲取最后一個元素,但不刪除:book01
true
true
新棧:[booknew01, book02, book03, book01, booknew02]
LinkedList
LinkedList概述
LinkedList實現List,同時也實現了Deque,可以當做雙端隊列來使用,可以當做“棧”或“隊列”使用。
LinkedList與ArrayList、ArrayDeque不同之處在於底層實現,LinkedList底層是通過鏈表的形式存儲元素,隨機訪問性能比較差,但是在插入、刪除的時候性能比較好(只需要改變指針所指的地址就行)
Q&A
peek()和element()的異同
- 同:peek()和element()都是在不移除的情況下返回隊頭;
- 異:peek()方法在隊列為空時返回null,而element()會拋出NoSuchElementException異常。
poll()和remove()的異同
- 同:poll()和remove()都是將移除並返回隊頭;
- 異:poll()在隊列為空時返回null,而remove()會拋出NoSuchElementException異常。
隊列和棧區別?
隊列
- 隊列是按照
先進先出FIFO原則進行操作元素的。 - 隊列是限定所有的插入只能在表的一端進行,而刪除在表的另一端進行的線性表。
- 表中允許插入的一端為隊尾,允許刪除的一端為隊頭。
棧
4. 棧是一種特殊的線性表,是一種后進先出LIFO的結構;
5. 棧是先定僅在表尾插入和刪除運算的線性表,表尾即為棧頂,表頭稱為棧底。
6. 棧的物理存儲可以用熟悉順序存儲結構,也可以用鏈式存儲結構。
