HOWTO · Java
Java でのエンキューとデキュー
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 を返します。この2つのメソッドでは、例外で知らせるか、特別な戻り値で知らせるかを選べます。poll() と peek() は先頭の値がないことを null で示すため、格納された値とその結果を区別する必要がある場合は、キューに null を入れないようにしましょう。
LinkedList でエンキューとデキューを実装する
次の完全なプログラムでは、Queue<String> インターフェースを LinkedList<String> で実装しています。2つの値を追加し、先頭を確認してから、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 を削除せずに読み取り、その後の2回の poll() 呼び出しで First、続いて Second を取り出します。型を Queue<String> として宣言しているため、コードは必要なキュー操作に依存し、具体的な実装は LinkedList が担います。容量や順序の動作が用途に合えば、別の Queue 実装に置き換えることもできます。
重要なのは、呼び出し側で必要な空キュー時と容量制限時の扱いを選ぶことです。戻り値を通常の制御フローで使う場合は offer、poll、peek を、対応する異常条件を呼び出し側に例外として知らせる場合は add、remove、element を使います。