ヘッダー画像

Javaのコレクション「Queue」「Deque」とは?便利な使い方も紹介!

投稿 2022年4月30日 最終更新 2022年4月30日 専門用語少なめ

Queueとは?

ざっくり言うと、一方通行の道路です。

Uターンは禁止(というかそんな幅ないでしょうし)で、もちろんバックも禁止です。

追い抜かすこともできないので、必ず入った順番通りに出てくます。

だいたいそんな感じです。

このことをFIFO(First In First Out)とも呼びます。

最初に(First)入った(In)ものが、最初に(First)出る(Out)感じです。

Dequeとは?

デックと読みます(デキューじゃないのか)

さきほどのQueueと対になる存在で、LIFO(Last In First Out)とも呼ばれます。

最後に(Last)入った(In)ものが、最初に(First)出る(Out)感じです。
※FILOともいいますが、真逆の言い方してるだけで一緒の意味です。

何かが積み重なっていくイメージですね。

一方通行の道路だと思ったら、行き止まりやんけ!みたいな状況です。

出ようにも後ろに車がいたら、後ろの車から出て行ってもらうしかないですね。

ただDequeは実はQueueを拡張しているものになるので、FIFO・LIFO両方使うことができます。

そのため、Dequeを使用することが多いかと思います。

なんせそのほうが便利ですからね。

Queueの種類

QueueやDequeとはあくまで入れ物のようなもの(インターフェース)なだけで、
実際動作する実物は以下の通りです。

ArrayDeque

一般的な両端キュー(FIFO・LIFO)

PriorityQueue

自然な順序付けで優先順位を決める優先キュー

マルチスレッドに対応したQueue

今回は紹介だけですが、マルチスレッドに対応したQueueも存在します。

「BlockingQueue」「BlockingDeque」「TransferQueue」というインターフェースで、
「LinkedBlockingQueue」「LinkedBlockingDeque」「LinkedTransferQueue」

「ArrayBlockingQueue」「SynchronousQueue」「DelayQueue」「PriorityBlockingQueue」
などと、なんかすごいいっぱいあります・・・。

もしマルチスレッドを使用する環境で使用するのであれば、こういう事を考慮しないといけません。

宣言する型について

一般的に下記のような宣言を見ることが多いかと思います。

Deque<String> 変数名 = new ArrayDeque<>();

このように、QueueやDequeの中に実物を入れていることが多いと思います。

ただ同じ型に入れることももちろん可能です。

ArrayDeque<String> 変数名 = new ArrayDeque<>();

どう違うのかと言うと、使える機能が違います。

細かくいえば他にも違いはありますが、基本的にはQueueやDeque等のインターフェースに格納し、
必要に応じてインターフェースに無い機能を使いたい時だけArrayDeque等を使用するイメージで大丈夫だと思います。

そのため以下は全てQueueやDequeに格納しております。

基本的な使い方

まずQueueやDequeの中身のことは「要素」と呼びます。

初期化する

Queueオブジェクトを初期化(生成)します。

基本的に引数は指定しなくてもいいですが、「初期容量」を指定できます。

何かというと、オブジェクト生成時にまず、初期容量分の保存領域を確保します。

そして要素を追加していく中で、初期容量の負荷係数個に到達すると、保存領域を拡張します。

この要領を拡張するという動作が非常に重たい動作になるので、できる限り最適に設定していきたいので、
最初からある程度量が分かっているのであれば、指定してあげるとパフォーマンスがよくなります。

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> deque1 = new ArrayDeque<>();
    // 初期容量100のインスタンスを生成
    Deque<String> deque2 = new ArrayDeque<>(100);
  }
}

要素を追加する

要素を追加するときは、最初か最後に追加することになります。

「add」は、追加に失敗した場合、例外が発生します。

「offer」は、追加に成功した場合はtrueを、失敗した場合はfalseを返却してくれます。

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCar = new ArrayDeque<>();
    // 先頭に追加(失敗時例外)
    // [車A]
    orderByCar.addFirst("車A");
    // 末尾に追加(失敗時例外)
    // [車A, 車B]
    orderByCar.addLast("車B");
    // 先頭に追加(成否結果返却)
    // [車C, 車A, 車B]
    orderByCar.offerFirst("車C");
    // 末尾に追加(成否結果返却)
    // [車C, 車A, 車B, 車D]
    orderByCar.offerLast("車D");
  }
}

要素を取得 & 削除する

要素の最初か最後を取得しつつ削除します。

「remove」は、取得(削除)に成功した場合は取得した値を返却し、失敗した場合は例外が発生します。

「poll」は、取得(削除)に成功した場合は取得した値を、追加に失敗した場合はnullを返却してくれます。

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCar = new ArrayDeque<>();
    // 追加 [車A, 車B, 車C, 車D, 車E]
    orderByCar.addLast("車A");
    orderByCar.addLast("車B");
    orderByCar.addLast("車C");
    orderByCar.addLast("車D");
    orderByCar.addLast("車E");
    // 先頭を取得&削除(失敗時例外) > 車A
    // [車B, 車C, 車D, 車E]
    orderByCar.removeFirst();
    // 末尾を取得&削除(失敗時例外) > 車E
    // [車B, 車C, 車D]
    orderByCar.removeLast();
    // 先頭を取得&削除(失敗時null) > 車B
    // [車C, 車D]
    orderByCar.pollFirst();
    // 末尾を取得&削除(失敗時null) > 車D
    // [車C]
    orderByCar.pollLast();
  }
}

要素を取得する

要素の最初か最後を取得します。

先ほどとは違い、取得するだけで削除はされません。

「get」は、取得に成功した場合は取得した値を返却し、失敗した場合は例外が発生します。

「peek」は、取得に成功した場合は取得した値を、追加に失敗した場合はnullを返却してくれます。

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCar = new ArrayDeque<>();
    // 追加 [車A, 車B, 車C]
    orderByCar.addLast("車A");
    orderByCar.addLast("車B");
    orderByCar.addLast("車C");
    // 先頭を取得(失敗時例外) > 車A
    orderByCar.getFirst();
    // 末尾を取得(失敗時例外) > 車C
    orderByCar.getLast();
    // 先頭を取得(失敗時null) > 車A
    orderByCar.peekFirst();
    // 末尾を取得(失敗時null) > 車C
    orderByCar.peekLast();
  }
}

要素の数を取得する

QueueやDeque内の要素の数を取得します。

取得できる数は人間が数える数字と同じなので、1個・2個と数えるやり方と同じです。

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCar = new ArrayDeque<>();
    // 中身の数を取得 > 0
    orderByCar.size();
    // 追加 [車A]
    orderByCar.addLast("車A");
    // 中身の数を取得 > 1
    orderByCar.size();
    // 追加 [車A, 車B]
    orderByCar.addLast("車B");
    // 中身の数を取得 > 2
    orderByCar.size();
  }
}

要素があるか判定する

QueueやDequeに要素があるかどうかを判定します。

ただし完全一致しないと存在しないと判定されます。

例だと「車A」に「車」は含まれてはいますが、
完全一致はしないので、containsはfalseを返します。

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCar = new ArrayDeque<>();
    // 追加 [車A, 車B, 車C]
    orderByCar.addLast("車A");
    orderByCar.addLast("車B");
    orderByCar.addLast("車C");
    // 中身に存在するかを判定
    if (orderByCar.contains("車B")) {
      // 今回は存在するのでtrue
    }
    if (!orderByCar.contains("車")) {
      // 今回は完全一致しないのでtrue
    }
  }
}

便利な使い方

Queueとして動かす

先ほどまでDequeで動かしていましたが、もちろんQueueとしてでも動かせます。

ただ最初か最後、どちらに追加されるかを意識しないと、少しわかりにくいです。

使い方は、Dequeで紹介したメソッドの「First」「Last」がないバージョンです。

追加する

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCarDeque = new ArrayDeque<>();
    // 末尾に追加(失敗時例外)
    // [車A]
    orderByCarDeque.add("車A");
    // 末尾に追加(成否結果返却)
    // [車A, 車B]
    orderByCarDeque.offer("車B");
    // LIFOに変換
    Queue<String> orderByCarQueue = Collections.asLifoQueue(orderByCarDeque);
    // 先頭に追加(失敗時例外)
    // [車C, 車A, 車B]
    orderByCarQueue.add("車C");
    // 先頭に追加(成否結果返却)
    // [車D, 車C, 車A, 車B]
    orderByCarQueue.offer("車D");
  }
}

取得 & 削除する

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCarDeque = new ArrayDeque<>();
    // 追加 [車A, 車B, 車C, 車D, 車E]
    orderByCarDeque.addLast("車A");
    orderByCarDeque.addLast("車B");
    orderByCarDeque.addLast("車C");
    orderByCarDeque.addLast("車D");
    orderByCarDeque.addLast("車E");
    // 先頭を取得&削除(失敗時例外) > 車A
    // [車B, 車C, 車D, 車E]
    orderByCarDeque.remove();
    // 先頭を取得&削除(失敗時null) > 車B
    // [車C, 車D, 車E]
    orderByCarDeque.poll();
    // LIFOに変換
    Queue<String> orderByCarQueue = Collections.asLifoQueue(orderByCarDeque);
    // 先頭を取得&削除(失敗時例外) > 車C
    // [車D, 車E]
    orderByCarQueue.remove();
    // 先頭を取得&削除(失敗時null) > 車D
    // [車E]
    orderByCarQueue.poll();
  }
}

取得する

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

public class QueueTest {
  public static void main(String[] args) {
    // インスタンスを生成
    Deque<String> orderByCarDeque = new ArrayDeque<>();
    // 追加 [車A, 車B, 車C]
    orderByCarDeque.addLast("車A");
    orderByCarDeque.addLast("車B");
    orderByCarDeque.addLast("車C");
    // 先頭を取得(失敗時例外) > 車A
    orderByCarDeque.element();
    // 先頭を取得(失敗時null) > 車A
    orderByCarDeque.peek();
    // LIFOに変換
    Queue<String> orderByCarQueue = Collections.asLifoQueue(orderByCarDeque);
    // 先頭を取得(失敗時例外) > 車A
    orderByCarQueue.element();
    // 先頭を取得(失敗時null) > 車A
    orderByCarQueue.peek();
  }
}

まとめ

Javaのコレクションの「Queue」「Deque」の紹介でした。

QueueやDequeに限らずにJavaのコレクションを使いこなせれば、
楽に処理を実装できますし、わかりやすく書けますので、WinWinです。

使いこなせれば世界が変わるといっても過言ではないと思います!

以上、ここまで見ていただきありがとうございます。

皆さまの快適な開発ライフに、ほんの少しでもお役に立てれば幸いです。

コメント

Javaのコレクション「Queue」「Deque」とは?便利な使い方も紹介! | いんくの開発うんちく集
[url=http://www.gm2r7g8836kby9hq8v80upo9586pwq16s.org/]ubxfolqnryz[/url]
bxfolqnryz http://www.gm2r7g8836kby9hq8v80upo9586pwq16s.org/
<a href="http://www.gm2r7g8836kby9hq8v80upo9586pwq16s.org/">abxfolqnryz</a>
Javaのコレクション「Queue」「Deque」とは?便利な使い方も紹介! | いんくの開発うんちく集
<a href="http://www.gdajc5n4931trvwd9g479m083y867x1qs.org/">adwqgvntvkw</a>
dwqgvntvkw http://www.gdajc5n4931trvwd9g479m083y867x1qs.org/
[url=http://www.gdajc5n4931trvwd9g479m083y867x1qs.org/]udwqgvntvkw[/url]