検索

キーワード


【Java】Queue, Deque の違いと代表的な<例外付き / 例外なし>メソッドの使い方

  • 公開日:2020-07-28 16:53:59
  • 最終更新日:2021-01-25 17:57:55
【Java】Queue, Deque の違いと代表的な<例外付き / 例外なし>メソッドの使い方

こんにちは、駆け出しプログラマーの若江です!

ここでは初学者として学習を終えた私が、アウトプットの意味も込めてコレクションのQueue, Dequeについてご紹介させていただきます。

できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!


関連記事リンク:コレクションの概要 / コレクション (List) の紹介 / コレクション(Set)の紹介 / コレクション(Map)の紹介 / コレクション(Iterator)の紹介

コレクション:Queue, Deque インターフェース ~例外付き&例外なしメソッド~

複数データを持つことができるコレクションの中でも、

「先入れ先出し(FIFO)」や「後入れ先出し(LIFO)」の特徴を持つのが Queue と Deque(デック) です。

ここでは Queue と Deque の関係や、ArrayDequeについて紹介します。


QueueインターフェースとDequeインターフェースの関係

Queueインターフェースを継承してできたのがDequeインターフェースです。

Queue:データを格納した順番に取り出せる「先入れ先出し(FIFO)」の特徴を持ちます。

  FIFO 例) a から順に a, b, c, d とデータを格納すると最初に格納したデータ a から順に a, b, c, d とデータが取り出される。

Deque:先入れ先出しに加えて、最後に格納したデータから順番に取り出せる「後入れ先出し(LIFO)」の特徴を持ちます。

  LIFO 例) a から順に a, b, c, d とデータを格納すると最後に格納したデータ d から順に d, c, b, a とデータが取り出される。


これらインターフェースを実装することで、可変長配列の特徴を持ったクラスを扱うことができます。

※Dequeは「Double ended queue(両端キュー)」の略です。

※FIFOは「First in first out」の略です。

※LIFOは「Last in first out」の略です。


ArrayDeque

Dequeインターフェースを実装したクラスです。

格納するデータ数に制限なく FIFO / LIFO を行える特徴を持ちます。

・ArrayDequeの書き方: Deque< 型 > 変数名 = new ArrayDeque< 型 >()


基本的にデータの「追加」「取り出し/削除」「検索」は先頭または末尾のデータから順となります。

またnullの保持を許容しません。

上記ArrayDequeの書き方を参考にサンプルコードを見てみましょう。

import java.util.Deque;
import java.util.ArrayDeque;
// String型のArrayDequeインスタンス生成
Deque<String> deque = new ArrayDeque<String>();
deque.add("a");
deque.add("b");
deque.add("c");

System.out.println(deque);

※DequeはQueueインターフェースを継承しているため、Queue<String> deque = new ArrayDeque<String>(); でも通りますが、一般的な構文はサンプルコードの書き方です。


QueueとDequeのメソッド

QueueとDequeのメソッドを理解すると、

先ほど紹介したArrayDequeでメソッドを使えるようになります。

まずは基本となるQueueのメソッドを見てみましょう。

メソッドの紹介にあたり、キューの「先頭」は格納されたデータが奥へ押しやられる先です。「末尾」は最新の格納されたデータです。


キューのイメージ(データの流れ方):

 (先頭)<キュー:a, b, c, d>(末尾) ◀a~dのデータを順に格納


Queueのメソッド

Queueには大きく分けて2タイプのメソッドがあります。

また、データ格納の容量に制限があることも理解しておきましょう。

※先述した通り ArrayDeque には容量制限がありません。

※以降サンプルコードではimportを省略しています。


メソッドタイプ1 (例外付き)

2タイプの内の1つは想定外の操作があった際に例外を返すパターンです。

    add   :指定されたデータを末尾に追加します。

      容量をオーバーするデータを格納しようとすると例外が投げられます。

Deque<String> deque = new ArrayDeque<String>();
deque.add("a"); // a を追加
deque.add("b"); // b を追加

System.out.println(deque); // 結果:a,b を表示


remove:キューの先頭からデータを一つ取り出します。このときキューからはデータが削除されます

      キュー内のデータが空で、削除できるデータがない場合に例外を投げます。

Deque<String> deque = new ArrayDeque<String>();
deque.add("a"); // デックに a を追加

System.out.println(deque.remove()); // a を取り出し表示
System.out.println(deque); // デックが空になる
System.out.println(deque.remove()); // 空のため例外をスロー


elementキューの先頭からデータを一つ取り出します。このときキューからはデータが削除されません

      検索できるデータが見つからない場合に例外を投げます。

Deque<String> deque = new ArrayDeque<String>();
deque.add("a"); // a を追加

System.out.println(deque.element()); // a を取り出し表示
System.out.println(deque); // 削除されていないため a を表示 
deque.remove(); // a を削除
System.out.println(deque.element()); // デックが空のため例外をスロー




メソッドタイプ2 (例外なし)

もう一つは例外を返すことなくnullやfalseを返すパターンです。

データ操作に対してfalseやnullが想定される場合に用いられます。

offer指定されたデータを末尾に追加します。

    追加に失敗した場合は false を返します。

Deque<String> deque = new ArrayDeque<String>();
deque.offer("a"); // a をデックに追加

System.out.println(deque); // a を表示


poll キューの先頭からデータを一つ取り出します。このときキューからはデータが削除されます

    キュー内のデータが空で、削除できるデータがない場合に null を返します。

Deque<String> deque = new ArrayDeque<String>();
deque.offer("a"); // デックに a を追加
System.out.println(deque); // a がデックにあることを確認

System.out.println(deque.poll()); // a を取り出して表示
System.out.println(deque); // デックが空になる
deque.poll(); // 空から取り出そうとしているが、例外は発生しない
System.out.println(deque.poll()); // null が返ってきていることを確認


peekキューの先頭からデータを一つ取り出します。このときキューからはデータが削除されません

    検索できるデータがない場合に null を返します。

Deque<String> deque = new ArrayDeque<String>();
deque.offer("a"); // a をデックに追加
System.out.println(deque); // デックに a があることを確認

System.out.println(deque.peek()); // a を取り出し
System.out.println(deque); // デックに a が残っていることを確認
System.out.println(deque.poll()); // a を取り出し削除
System.out.println(deque); // デックの中身が空であることを確認
deque.peek(); // 空のデックを探そうとしても、例外は発生しない
System.out.println(deque.peek()); // null が返っていることを確認



Dequeのメソッド

先ほどのQueueを踏まえてDequeが持つメソッドを確認しましょう。

Dequeは紹介した通り、先頭/末尾両方からデータの操作が可能です。

そのためQueueのメソッドの考え方に加えて「先頭から」や「末尾から」といった2つの指示に分かれます。


メソッドタイプ1 (例外付き)

   addFirst   指定されたデータを先頭に追加します。

        容量をオーバーするデータを格納しようとすると例外が投げられます。

   addLast   指定されたデータを末尾に追加します。

        容量をオーバーするデータを格納しようとすると例外が投げられます。(Queue の add と同じ動きをします)

Deque<String> deque = new ArrayDeque<String>();
deque.add("a"); // a をデックに追加
System.out.println(deque); // a がデックにあることを確認

deque.addFirst("b"); // a の前(先頭)に b を追加
deque.addLast("c"); // a の後(末尾)に c を追加
System.out.println(deque); // b, a, c が表示される


removeFirstキューの先頭からデータを一つ取り出します。このときキューからはデータが削除されます

        キュー内のデータが空だと例外を投げます。

removeLastキューの末尾からデータを一つ取り出します。このときキューからはデータが削除されます

        キュー内のデータが空だと例外を投げます。(Queue の remove と同じ動きをします)

Deque<String> deque = new ArrayDeque<String>();
deque.add("a");
deque.add("b");
deque.add("c");
System.out.println(deque); // デックに a, b, c があることを確認

System.out.println(deque.removeFirst()); // a (先頭)を取り出して表示、削除
System.out.println(deque); // デックに b, c があることを確認
System.out.println(deque.removeLast()); // c (末尾)を取り出して表示、削除
System.out.println(deque); // 残りが b でことを確認


   getFirst   キューの先頭からデータを一つ取り出します。このときキューからはデータが削除されません

        検索できるデータが見つからない場合に例外を投げます。

   getLast    キューの末尾からデータを一つ取り出します。このときキューからはデータが削除されません

        検索できるデータが見つからない場合に例外を投げます。(Queue の get と同じ動きをします)

Deque<String> deque = new ArrayDeque<String>();
deque.add("a");
deque.add("b");
deque.add("c");
System.out.println(deque); // デックに a, b, c があることを確認

System.out.println(deque.getFirst()); // a (先頭)を取り出し
System.out.println(deque); // a が残ったままで a, b, c があることを確認
System.out.println(deque.getLast()); // c (末尾)を取り出し
System.out.println(deque); // c が残ったままで a, b, c があることを確認



メソッドタイプ2 (例外なし)

offerFirst 指定されたデータを先頭に追加します。

       追加に失敗した場合は false を返します。

offerLast 指定されたデータを末尾に追加します。

       追加に失敗した場合は false を返します。(Queue の offer と同じ動きをします。)

// 「false / 例外」以外は基本的に add と同じ結果になります。
Deque<String> deque = new ArrayDeque<String>();
deque.offer("a");
System.out.println(deque);

deque.offerFirst("b");
deque.offerLast("c");
System.out.println(deque); // b, a, c を表示


pollFirst キューの先頭からデータを一つ取り出します。このときキューからはデータが削除されます

       キュー内のデータが空だと null を返します。

pollLast キューの末尾からデータを一つ取り出します。このときキューからはデータが削除されます

       キュー内のデータが空だと null を返します。(Queue の poll と同じ動きをします。)

// 「null / 例外」以外は基本的に remove と同じ動きをします。
Deque<String> deque = new ArrayDeque<String>();
deque.offer("a");
deque.offer("b");
deque.offer("c");
System.out.println(deque);

System.out.println(deque.pollFirst()); // a を取り出し、削除
System.out.println(deque); // b, c が残っていることを確認
System.out.println(deque.pollLast()); // c を取り出し、削除
System.out.println(deque); // b が残っていることを確認


peekFirstキューの先頭からデータを一つ取り出します。このときキューからはデータが削除されません

       検索できるデータがない場合に null を返します。

peekLastキューの末尾からデータを一つ取り出します。このときキューからはデータが削除されません

       検索できるデータがない場合に null を返します。(Queue の peek と同じ動きをします。)

// 「null / 例外」以外は基本的に get と同じ動きをします。
Deque<String> deque = new ArrayDeque<String>();
deque.offer("a");
deque.offer("b");
deque.offer("c");
System.out.println(deque);

System.out.println(deque.peekFirst()); // a を取り出し
System.out.println(deque); // a, b, c が残っていることを確認
System.out.println(deque.peekLast()); // c を取り出し
System.out.println(deque); // a, b, c が残っていることを確認


以上が代表的なメソッドとなります。

Queue と Deque 、例外あり/なしで若干複雑ですが基本的な動作は「追加」「取り出し/削除」「検索」の3つです。

紹介したメソッドをArrayDequeで使ってデータ操作を行うことができます。



まとめ

Queueインターフェースを継承した Dequeインターフェースがあり、

Dequeインターフェースを実装したArrayDequeクラスがあります。

ArrayDequeは先頭/末尾、両端からのデータ操作が可能となっています。

また基本的なデータ操作メソッドは「追加」「取り出し/削除」「検索」の3つとなり、

例外を返すパターンと、例外を返さないパターンに分かれます。

コレクションは複数種類あるので、場面によって適切に使い分けるよう心掛けていきましょう。


関連記事リンク

コレクションの概要 / コレクション (List) の紹介 / コレクション(Set)の紹介 / コレクション(Map)の紹介 / コレクション(Iterator)の紹介


【著者】

若江

30代で異業種となるIT業界へ転職した駆け出しのプログラマです。これまで主に Java や Ruby、HTML/CSS を使って学習を目的としたショップサイトや掲示板サイトの作成を行いました。プログラマとしての経験が浅いからこそ、未経験者の目線に近い形で基礎の紹介をしていきたいと思います。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様