隊列(queue)簡述
隊列(queue)是一種常用的數據結構,可以將隊列看做是一種特殊的線性表,該結構遵循的先進先出原則。Java中,LinkedList實現了Queue接口,因為LinkedList進行插入、刪除操作效率較高。
在處理元素前用於保存元素的 collection。除了基本的 Collection
操作外,隊列還提供其他的插入、提取和檢查操作。每個方法都存在兩種形式:一種拋出異常(操作失敗時),另一種返回一個特殊值(null 或 false,具體取決於操作)。插入操作的后一種形式是用於專門為有容量限制的 Queue 實現設計的;在大多數實現中,插入操作不會失敗。
拋出異常 | 返回特殊值 | |
插入 | add(e) |
offer(e) |
移除 | remove() |
poll() |
檢查 | element() |
peek() |
隊列通常(但並非一定)以 FIFO(先進先出)的方式排序各個元素。不過優先級隊列和 LIFO 隊列(或堆棧)例外,前者根據提供的比較器或元素的自然順序對元素進行排序,后者按 LIFO(后進先出)的方式對元素進行排序。無論使用哪種排序方式,隊列的頭 都是調用 remove()
或 poll()
所移除的元素。在 FIFO 隊列中,所有的新元素都插入隊列的末尾。其他種類的隊列可能使用不同的元素放置規則。每個 Queue 實現必須指定其順序屬性。
Queue 接口並未定義阻塞隊列的方法,而這在並發編程中是很常見的。BlockingQueue
接口定義了那些等待元素出現或等待隊列中有可用空間的方法,這些方法擴展了此接口。
Queue 實現通常不允許插入 null 元素,盡管某些實現(如 LinkedList
)並不禁止插入 null。即使在允許 null 的實現中,也不應該將 null 插入到 Queue 中,因為 null 也用作 poll 方法的一個特殊返回值,表明隊列不包含元素。
Queue 實現通常未定義 equals 和 hashCode 方法的基於元素的版本,而是從 Object 類繼承了基於身份的版本,因為對於具有相同元素但有不同排序屬性的隊列而言,基於元素的相等性並非總是定義良好的。
Queue常用方法:
- boolean add(E e);將指定的元素插入此隊列(如果立即可行且不會違反容量限制),在成功時返回 true,如果當前沒有可用的空間,則拋出 IllegalStateException。
- boolean offer(E e);將指定的元素插入此隊列(如果立即可行且不會違反容量限制),當使用有容量限制的隊列時,此方法通常要優於
add(E)
,后者可能無法插入元素,而只是拋出一個異常。 - E remove();獲取並移除此隊列的頭。
- E poll();獲取並移除此隊列的頭,如果此隊列為空,則返回 null。
- E element();獲取,但是不移除此隊列的頭。
- E peek();獲取但不移除此隊列的頭;如果此隊列為空,則返回 null。
雙端隊列(Deque)簡述
雙向隊列(Deque),是Queue的一個子接口,雙向隊列是指該隊列兩端的元素既能入隊(offer)也能出隊(poll),如果將Deque限制為只能從一端入隊和出隊,則可實現棧的數據結構。對於棧而言,有入棧(push)和出棧(pop),遵循先進后出原則。
一個線性 collection,支持在兩端插入和移除元素。名稱 deque 是“double ended queue(雙端隊列)”的縮寫,通常讀為“deck”。大多數 Deque 實現對於它們能夠包含的元素數沒有固定限制,但此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列。
此接口定義在雙端隊列兩端訪問元素的方法。提供插入、移除和檢查元素的方法。每種方法都存在兩種形式:一種形式在操作失敗時拋出異常,另一種形式返回一個特殊值(null 或 false,具體取決於操作)。插入操作的后一種形式是專為使用有容量限制的 Deque 實現設計的;在大多數實現中,插入操作不能失敗。
下表總結了上述 12 種方法:
第一個元素(頭部) | 最后一個元素(尾部) | |||
拋出異常 | 特殊值 | 拋出異常 | 特殊值 | |
插入 | addFirst(e) |
offerFirst(e) |
addLast(e) |
offerLast(e) |
移除 | removeFirst() |
pollFirst() |
removeLast() |
pollLast() |
檢查 | getFirst() |
peekFirst() |
getLast() |
peekLast() |
此接口擴展了 Queue
接口。在將雙端隊列用作隊列時,將得到 FIFO(先進先出)行為。將元素添加到雙端隊列的末尾,從雙端隊列的開頭移除元素。從 Queue 接口繼承的方法完全等效於 Deque 方法,如下表所示:
此接口擴展了 Queue
接口。在將雙端隊列用作隊列時,將得到 FIFO(先進先出)行為。將元素添加到雙端隊列的末尾,從雙端隊列的開頭移除元素。從 Queue 接口繼承的方法完全等效於 Deque 方法,如下表所示:
Queue 方法 | 等效 Deque 方法 |
add(e) |
addLast(e) |
offer(e) |
offerLast(e) |
remove() |
removeFirst() |
poll() |
pollFirst() |
element() |
getFirst() |
peek() |
peekFirst() |
雙端隊列也可用作 LIFO(后進先出)堆棧。應優先使用此接口而不是遺留 Stack
類。在將雙端隊列用作堆棧時,元素被推入雙端隊列的開頭並從雙端隊列開頭彈出。堆棧方法完全等效於 Deque 方法,如下表所示:
堆棧方法 | 等效 Deque 方法 |
push(e) |
addFirst(e) |
pop() |
removeFirst() |
peek() |
peekFirst() |
注意,在將雙端隊列用作隊列或堆棧時,peek
方法同樣正常工作;無論哪種情況下,都從雙端隊列的開頭抽取元素。
此接口提供了兩種移除內部元素的方法:removeFirstOccurrence
和 removeLastOccurrence
。
與 List
接口不同,此接口不支持通過索引訪問元素。
雖然 Deque 實現沒有嚴格要求禁止插入 null 元素,但建議最好這樣做。建議任何事實上允許 null 元素的 Deque 實現用戶最好不 要利用插入 null 的功能。這是因為各種方法會將 null 用作特殊的返回值來指示雙端隊列為空。
Deque 實現通常不定義基於元素的 equals 和 hashCode 方法,而是從 Object 類繼承基於身份的 equals 和 hashCode 方法。
- 從以下版本開始:
- 1.6
方法摘要 | |
---|---|
boolean |
add(E e) 將指定元素插入此雙端隊列所表示的隊列(換句話說,此雙端隊列的尾部),如果可以直接這樣做而不違反容量限制的話;如果成功,則返回 true,如果當前沒有可用空間,則拋出 IllegalStateException。 |
void |
addFirst(E e) 將指定元素插入此雙端隊列的開頭(如果可以直接這樣做而不違反容量限制)。 |
void |
addLast(E e) 將指定元素插入此雙端隊列的末尾(如果可以直接這樣做而不違反容量限制)。 |
boolean |
contains(Object o) 如果此雙端隊列包含指定元素,則返回 true。 |
Iterator<E> |
descendingIterator() 返回以逆向順序在此雙端隊列的元素上進行迭代的迭代器。 |
E |
element() 獲取,但不移除此雙端隊列所表示的隊列的頭部(換句話說,此雙端隊列的第一個元素)。 |
E |
getFirst() 獲取,但不移除此雙端隊列的第一個元素。 |
E |
getLast() 獲取,但不移除此雙端隊列的最后一個元素。 |
Iterator<E> |
iterator() 返回以恰當順序在此雙端隊列的元素上進行迭代的迭代器。 |
boolean |
offer(E e) 將指定元素插入此雙端隊列所表示的隊列(換句話說,此雙端隊列的尾部),如果可以直接這樣做而不違反容量限制的話;如果成功,則返回 true,如果當前沒有可用的空間,則返回 false。 |
boolean |
offerFirst(E e) 在不違反容量限制的情況下,將指定的元素插入此雙端隊列的開頭。 |
boolean |
offerLast(E e) 在不違反容量限制的情況下,將指定的元素插入此雙端隊列的末尾。 |
E |
peek() 獲取,但不移除此雙端隊列所表示的隊列的頭部(換句話說,此雙端隊列的第一個元素);如果此雙端隊列為空,則返回 null。 |
E |
peekFirst() 獲取,但不移除此雙端隊列的第一個元素;如果此雙端隊列為空,則返回 null。 |
E |
peekLast() 獲取,但不移除此雙端隊列的最后一個元素;如果此雙端隊列為空,則返回 null。 |
E |
poll() 獲取並移除此雙端隊列所表示的隊列的頭部(換句話說,此雙端隊列的第一個元素);如果此雙端隊列為空,則返回 null。 |
E |
pollFirst() 獲取並移除此雙端隊列的第一個元素;如果此雙端隊列為空,則返回 null。 |
E |
pollLast() 獲取並移除此雙端隊列的最后一個元素;如果此雙端隊列為空,則返回 null。 |
E |
pop() 從此雙端隊列所表示的堆棧中彈出一個元素。 |
void |
push(E e) 將一個元素推入此雙端隊列所表示的堆棧(換句話說,此雙端隊列的頭部),如果可以直接這樣做而不違反容量限制的話;如果成功,則返回 true,如果當前沒有可用空間,則拋出 IllegalStateException。 |
E |
remove() 獲取並移除此雙端隊列所表示的隊列的頭部(換句話說,此雙端隊列的第一個元素)。 |
boolean |
remove(Object o) 從此雙端隊列中移除第一次出現的指定元素。 |
E |
removeFirst() 獲取並移除此雙端隊列第一個元素。 |
boolean |
removeFirstOccurrence(Object o) 從此雙端隊列移除第一次出現的指定元素。 |
E |
removeLast() 獲取並移除此雙端隊列的最后一個元素。 |
boolean |
removeLastOccurrence(Object o) 從此雙端隊列移除最后一次出現的指定元素。 |
int |
size() 返回此雙端隊列的元素數。 |