HOWTO · Java
Java 中的 Enqueue 和 Dequeue
瞭解 Java 中的入隊和出隊以及所有其他相關資訊
本頁內容
在 Java 中,入隊會將元素加入 FIFO 佇列的尾端,出隊則會移除佇列首端的元素。Queue 介面定義了這些操作,而 LinkedList 是其中一種實作類別。如果需要透過回傳值判斷是否成功加入元素,或佇列首端是否有元素可取,請使用 offer 和 poll。
佇列與 FIFO
佇列會依照先進先出(FIFO)的順序處理元素:最先加入的值會最先移除。加入元素時會放在尾端,移除或查看元素時則會操作首端。當程式需要依序處理送出的工作、事件或訊息時,這種順序就很實用。
Java 集合框架中的 Queue 是一個介面。它定義了一般佇列操作,但不限定資料的儲存方式。不同實作可能有不同的容量限制與效能特性,因此應依照應用程式的需求選擇,不要假設所有佇列的行為都相同。
如需了解相關的排序規則,請參閱 Java FIFO 佇列指南。
入隊與出隊
入隊是將項目加入佇列尾端的操作;出隊則是移除佇列首端項目的操作。這些名稱描述的是佇列操作,不代表 Deque 介面等同於出隊操作。Deque 是另一個 Java 介面,適用於支援在兩端加入及移除元素的集合。
查看佇列首端的元素時,也可以不將它移除。當程式需要判斷下一個要處理的項目,同時又要維持佇列順序時,這種操作就很有用。
Java 中的 Queue 方法
加入元素時,add(E) 和 offer(E) 都會在佇列接受元素時將它加入。兩者在容量限制下的行為不同:如果容量限制使元素無法加入,add 會擲出 IllegalStateException,而 offer 會回傳 false。無界佇列可能沒有固定容量,因此實際結果取決於所使用的實作。
移除元素時,remove() 會取出並移除佇列首端的元素;如果佇列是空的,就會擲出 NoSuchElementException。poll() 也會取出並移除首端元素,但沒有元素可移除時會回傳 null。若佇列為空是預期情況,而且呼叫端應透過回傳值處理,請使用 poll()。
element() 和 peek() 都會查看佇列首端的元素,但不會將它移除。佇列為空時,element() 會擲出 NoSuchElementException,而 peek() 會回傳 null。你可以依需求選擇明確擲出例外,或以特殊回傳值表示沒有元素。由於 poll() 和 peek() 會用 null 表示沒有可用的首端元素,如果程式邏輯需要區分這種情況與實際儲存的值,就不要在佇列中存放 null。
使用 LinkedList 實作入隊與出隊
以下完整程式使用 Queue<String> 介面,並以 LinkedList<String> 作為實作。程式會加入兩個值、查看佇列首端,接著依 FIFO 順序逐一移除這些值。
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
queue.offer("First");
queue.offer("Second");
System.out.println("Head: " + queue.peek());
System.out.println("Removed: " + queue.poll());
System.out.println("Removed: " + queue.poll());
}
}
Head: First
Removed: First
Removed: Second
記錄中的執行結果如上所示。第一次查看會讀取 First,但不會將它移除;接著兩次呼叫 poll(),會依序移除 First 和 Second。程式將型別宣告為 Queue<String>,因此只依賴所需的佇列操作,並由 LinkedList 提供具體實作。只要其他 Queue 實作符合應用程式對容量與排序行為的需求,也可以替換使用。
選擇方法時,應考量呼叫端需要如何處理空佇列與容量限制:若回傳值是一般控制流程的一部分,請使用 offer、poll 和 peek;若遇到相應狀況時應將例外傳給呼叫端,則可使用 add、remove 和 element。