【プログラミングしてみよう51】JavaのStackとQueueの使い方

Java

前回はString.formatとprintfを使った書式指定を学びました。

今回は「Stack(スタック)」と「Queue(キュー)」について解説します。 ListやMapに続くコレクションの仲間で、データの取り出し順序に特徴があります。使い所を理解することで、より適切なデータ構造を選べるようになります。

StackとQueueとは

「Stack(スタック)」は**後入れ先出し(LIFO: Last In First Out)**のデータ構造です。積み重ねた皿のイメージで、最後に積んだ皿を最初に取り出します。

「Queue(キュー)」は**先入れ先出し(FIFO: First In First Out)**のデータ構造です。行列(並び列)のイメージで、最初に並んだ人が最初に取り出されます。

Stack: [1, 2, 3] → 取り出すと 3(最後に追加したもの)
Queue: [1, 2, 3] → 取り出すと 1(最初に追加したもの)

Javaでは以下のクラス・インターフェースを使います。

Deque<T>       // StackとQueueの両方として使える(推奨)
ArrayDeque<T>  // Dequeの実装クラス(高速)
LinkedList<T>  // DequeとListの両方を実装
Stack<T>       // 古いクラス(使用非推奨。Dequeを使うこと)
Queue<T>       // キューのインターフェース

サンプルコード(Stackの使い方)

ファイル作成

「Java39」フォルダに StackTest.java という名前でファイルを作成します

コード入力

以下のコードを入力します。

import java.util.ArrayDeque;
import java.util.Deque;

public class StackTest {
    public static void main(String[] args) {
        // ArrayDequeをStackとして使う
        Deque<String> stack = new ArrayDeque<>();

        // push: 先頭に追加
        stack.push("1番目");
        stack.push("2番目");
        stack.push("3番目");

        System.out.println("Stack: " + stack);
        System.out.println("サイズ: " + stack.size());

        // peek: 先頭を確認(取り出さない)
        System.out.println("peek: " + stack.peek());
        System.out.println("peek後のサイズ: " + stack.size());

        // pop: 先頭から取り出す(LIFO)
        System.out.println("\n--- pop ---");
        while (!stack.isEmpty()) {
            System.out.println("pop: " + stack.pop());
        }

        // 実用例: ブラウザの戻るボタン
        System.out.println("\n--- ブラウザ履歴 ---");
        Deque<String> history = new ArrayDeque<>();
        history.push("https://example.com");
        history.push("https://example.com/news");
        history.push("https://example.com/article/1");

        System.out.println("現在のページ: " + history.peek());
        history.pop(); // 戻る
        System.out.println("戻った先: " + history.peek());
        history.pop(); // もう一度戻る
        System.out.println("さらに戻った先: " + history.peek());
    }
}

コンパイル

javac StackTest.java

実行

java StackTest

実行結果は次のようになります。

Stack: [3番目, 2番目, 1番目]
サイズ: 3
peek: 3番目
peek後のサイズ: 3

--- pop ---
pop: 3番目
pop: 2番目
pop: 1番目

--- ブラウザ履歴 ---
現在のページ: https://example.com/article/1
戻った先: https://example.com/news
さらに戻った先: https://example.com

サンプルコード(Queueの使い方)

ファイル作成

「Java39」フォルダに QueueTest.java という名前でファイルを作成します

コード入力

以下のコードを入力します。

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;

public class QueueTest {
    public static void main(String[] args) {
        // ArrayDequeをQueueとして使う
        Queue<String> queue = new ArrayDeque<>();

        // offer: 末尾に追加
        queue.offer("1番目");
        queue.offer("2番目");
        queue.offer("3番目");

        System.out.println("Queue: " + queue);
        System.out.println("サイズ: " + queue.size());

        // peek: 先頭を確認(取り出さない)
        System.out.println("peek: " + queue.peek());
        System.out.println("peek後のサイズ: " + queue.size());

        // poll: 先頭から取り出す(FIFO)
        System.out.println("\n--- poll ---");
        while (!queue.isEmpty()) {
            System.out.println("poll: " + queue.poll());
        }

        // 実用例: 印刷キュー
        System.out.println("\n--- 印刷キュー ---");
        Queue<String> printQueue = new ArrayDeque<>();
        printQueue.offer("レポート.pdf");
        printQueue.offer("請求書.xlsx");
        printQueue.offer("写真.png");

        System.out.println("印刷待ち: " + printQueue);
        while (!printQueue.isEmpty()) {
            System.out.println("印刷中: " + printQueue.poll());
            System.out.println("残り: " + printQueue);
        }
        System.out.println("すべての印刷が完了しました");
    }
}

コンパイル

javac QueueTest.java

実行

java QueueTest

実行結果は次のようになります。

Queue: [1番目, 2番目, 3番目]
サイズ: 3
peek: 1番目
peek後のサイズ: 3

--- poll ---
poll: 1番目
poll: 2番目
poll: 3番目

--- 印刷キュー ---
印刷待ち: [レポート.pdf, 請求書.xlsx, 写真.png]
印刷中: レポート.pdf
残り: [請求書.xlsx, 写真.png]
印刷中: 請求書.xlsx
残り: [写真.png]
印刷中: 写真.png
残り: []
すべての印刷が完了しました

コードの解説

ArrayDeque は Deque(両端キュー)インターフェースを実装しており、StackとQueueの両方として使えます。古い Stack クラスは synchronized がかかっていてシングルスレッドでは非効率なため、現在は ArrayDeque の使用が推奨されています。

Stackとして使う場合は push(追加)・pop(取り出し)・peek(確認)を使います。push は先頭に追加し、pop は先頭から取り出すためLIFO(後入れ先出し)になります。ブラウザの戻るボタンや「元に戻す(Ctrl+Z)」のような「直前の操作を取り消す」機能に向いています。

Queueとして使う場合は offer(追加)・poll(取り出し)・peek(確認)を使います。offer は末尾に追加し、poll は先頭から取り出すためFIFO(先入れ先出し)になります。印刷キューやタスクの順番待ちなど「先に来たものを先に処理する」場面に向いています。

peek はどちらの場合も「次に取り出される要素を確認するが取り出しはしない」メソッドです。空のコレクションに対して peek を呼ぶと null を返し、pop や poll は null を返すか例外を投げます。

まとめ

StackはLIFO(後入れ先出し)で「直前のものを取り出す」場面に、QueueはFIFO(先入れ先出し)で「先に来たものを先に処理する」場面に使います。Javaではどちらも ArrayDeque を使って実装するのが現在の推奨です。Stackとして使うときは push/pop/peek、Queueとして使うときは offer/poll/peek を使い分けましょう。これでList・Map・Set・Stack・Queueと、Javaの主要なコレクションをすべて学んだことになります。

2026/07/30(木) ぱんまる

コメント

タイトルとURLをコピーしました