【Java】Dequeの構造と使い方:Queue・Stackの違いと使い分けについて

当ページのリンクには広告が含まれています。
エンジニア, パソコン, ノマド
目次

Dequeとは何か?

Dequeの概念

Dequeとは、両端キュー (double-ended queue) のことです。

データを両端から追加・削除できるのが特徴で、これはQueue と Stack の両方の特徴を持つことを意味します。

補足

Stack:片端のみで出し入れする(先入れ後出し)

Queue:片端から入れ、反対の片端から取り出す(先入れ先出し)

addFirst

removeFirst

addLast

removeLast

Dequeを使うメリット

  • 柔軟性: QueueとStackの両方の機能を持つため、様々なアルゴリズムやデータ構造の実現に利用できる。
  • 効率性: 適切な実装であれば、QueueやStackと比較して、より効率的な処理が可能できる。
  • シンプルさ: 複雑なデータ構造を組み合わせる必要がなく、シンプルな実装で済ませられる場合がある。

Deque の使い方

主な使用シーン

  • キューとスタックの両方の機能が必要な場合
    • 先に入力されたデータを後から処理したい場合と、後に入力されたデータを先に処理したい場合が混在する場合。
    • 両端から要素を追加・削除できるため、特定の要素へのアクセスが頻繁な場合。
  • 再帰的な処理
    • スタックのような機能を活用して、再帰的な処理を効率的に実装する場合。
  • 履歴管理
    • ブラウザの前ページ、次ページの移動など、履歴管理したい場合。
    • 編集履歴を保存し、Undo/Redo操作を行う場合。
  • パーサー:
    • 構文解析など、入力データを順次処理していく場合(一時的な情報保持に使われる)

Dequeのメソッド

両端ごとにメソッドがあります。

また、操作が完了しなかった際に例外をスローするメソッドと何らかの値(boolean、nullなど)を返すメソッドの2通りが用意されています。

操作先頭要素末尾要素
例外をthrow特別な値例外をthrow特別な値
追加addFirst(e)offerFirst(e)addLast(e)offerLast(e)
削除removeFirst()pollFirst()removeLast()pollLast()
確認getFirst()peekFirst()getLast()peekLast()

(※)追加・削除は要素の変更が発生しますが、確認は要素が何かを確認するだけ何も変更しません。

実装例

主に LinkedListArrayDeque で実装されます。それぞれ特徴が異なるため、用途に合わせて使い分けることが重要です。

LinkedList

双方向連結リストを基にした実装で、要素の挿入・削除が効率的です。特に、リストの先頭や末尾への要素の追加・削除がO(1)の時間で行えます。

ArrayDeque

配列を基にした実装で、LinkedList に比べてランダムアクセスが高速です。ただし、要素の挿入・削除に伴う配列の再配置が必要になる場合があり、性能が低下する可能性があります。

サンプルコード

LinkedListとArrayDequeの比較

特徴LinkedListArrayDeque
基底データ構造双方向連結リスト配列
要素の挿入・削除O(1)O(1)またはO(n) (配列の再配置が必要な場合)
ランダムアクセスO(n)O(1)
メモリ使用量 要素数に比例 一般的にLinkedListより少ない
  • どちらを選ぶべきか?
    • 要素の挿入・削除が頻繁な場合:LinkedList
    • ランダムアクセスが必要な場合:ArrayDeque
    • メモリ使用量を削減したい場合:ArrayDeque
ポイント

用途によって性能が変ってくることに注意してください。

Queue・Stackとの違い

Queueとは?

Queueは、先入れ先出し (First In First Out, FIFO) の原則に基づくデータ構造です。

入った順に出ていくことが保証されています。

Stackとは?

Stack は、後入れ先出し (Last In First Out, LIFO) の原則に基づくデータ構造です。

本を積み重ねる様子に例えることができます。

Deque・Queue・Stackの違い

各々の違いをまとめます。

特徴DequeQueueStack
要素の追加両端末尾のみ片端のみ
要素の削除両端先頭のみ片端のみ
用途・先入れ先出し、後入れ先出しの両方
・より柔軟なデータ構造が必要な場合
先入れ先出し 後入れ先出し

Deque・Queue・Stackの使い分け

Dequeを使うべきケース

  • QueueとStackの両方の機能が必要な場合(例:ブラウザの履歴管理)
  • データへのアクセスパターンが動的な場合(例:テキストエディタのUndo/Redo機能)
  • より柔軟なデータ構造が必要な場合(例:構文解析)

Queueを使うべきケース

  • タスクの処理順序を厳密に守りたい場合(例:印刷ジョブの待ち行列)
  • データを一度だけ処理したい場合(例:ネットワークパケットの処理)

Stackを使うべきケース

  • 関数呼び出しの履歴管理(例:スタックトレース)
  • 中置記法から後置記法への変換(例:中置記法の式を後置記法に変換するアルゴリズム)
  • 深さ優先探索(例:グラフ探索のアルゴリズム)

まとめると、各データ構造でしかできない処理で使い分けるのがポイントです。

まとめ

  • Dequeとは 両端キュー (double-ended queue) のことで、両端から追加・削除できる構造を持つ。
    • QueueとStackの特徴を併せ持っている。
  • 主な実装クラスとして、LinkedListArrayDequeがある。
    • 特徴があるので、用途によって使い分けること。
    • 要素の挿入・削除が頻繁な場合はLinkedList
    • ランダムアクセスが必要な場合やメモリ使用量を削減したい場合:はArrayDeque
  • Queue・Stackとの使い分けポイントは、各データ構造でしか実現できない場合であること。

最後までお読み頂き、ありがとうございました!
ご意見・ご要望がありましたら、遠慮なくコメント下さい!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

リーマンショックの影響で26歳の時にIT業界から離れ、紆余曲折を経て34歳でエンジニアに復帰。
現在はフリーランスエンジニア兼コアファクトリ合同会社代表。
得意な言語はJava。

新人教育経験あり(わからなくて進まない子を放置しない方針)
Javaの新人教育にお困りでしたらお声がけください。

■保有資格
・Java Gold SE 11

コメント

コメントする

CAPTCHA


目次