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 実装に置き換えることもできます。

Queue インターフェースを使ったエンキューとデキュー

重要なのは、呼び出し側で必要な空キュー時と容量制限時の扱いを選ぶことです。戻り値を通常の制御フローで使う場合は offer、poll、peek を、対応する異常条件を呼び出し側に例外として知らせる場合は add、remove、element を使います。