導入
Javaで「後入れ先出し(LIFO)」の構造が必要になったとき、皆さんはどのクラスを使っていますか?かつてはStackクラスが使われていましたが、現在はDequeインターフェースを使用するのがJavaの標準的なベストプラクティスです。なぜStackクラスを避けるべきなのか、そしてDequeを用いた安全で効率的な実装方法について解説します。
基礎知識
Deque(デック)は「Double Ended Queue」の略で、両端から要素の追加・削除ができるインターフェースです。JavaではArrayDequeやLinkedListが実装クラスとしてよく使われます。
スタック操作を行う際、Dequeは以下のメソッドを提供します。
push(E e): スタックの先頭に要素を追加します。
pop(): スタックの先頭から要素を取り出し、削除します。
なぜStackクラスではなくDequeを使うのか。それは、Stackクラスは古いJavaの設計思想を引き継いでおり、同期化によるパフォーマンス低下や、クラス階層の設計上の問題があるためです。Dequeはコレクションフレームワークとして最適化されており、パフォーマンスと安全性の面で優れています。
実装/解決策
Dequeでスタック操作を行う際は、ArrayDequeをインスタンス化するのが一般的です。ArrayDequeはメモリ効率が良く、Nullを許容しないため、スタックとしての用途に非常に適しています。
実装のポイントは「push」と「pop」をペアで使うことです。また、要素がない状態でpop()を呼び出すと「NoSuchElementException」が発生するため、必要に応じてisEmpty()で確認するか、例外処理を適切に行うことが重要です。
サンプルプログラム
import java.util.ArrayDeque;
import java.util.Deque;
public class StackExample {
public static void main(String[] args) {
// スタックとして使用するためにDequeを宣言
Deque
// データの積上げ (Push)
stack.push(“1段目”);
stack.push(“2段目”);
stack.push(“3段目”);
System.out.println(“現在のスタック: ” + stack);
// データの取り出し (Pop)
// 最後に積んだ「3段目」から順に取り出される
while (!stack.isEmpty()) {
String item = stack.pop();
System.out.println(“取り出したアイテム: ” + item);
}
}
}
応用・注意点
現場での開発において注意すべき点は、「目的がスタック操作であることを明示する」ことです。Dequeにはadd/removeといったキュー用のメソッドも存在しますが、スタックとして使う場合は、コードの可読性を高めるために必ずpush/popを使用してください。
また、スレッドセーフなスタックが必要な場合は、Dequeではなく「ConcurrentLinkedDeque」や「LinkedBlockingDeque」の利用を検討してください。通常のArrayDequeはマルチスレッド環境では安全ではないため、並行処理を行う際は注意が必要です。
最後に、Sequenced Collections(Java 21以降)の導入により、Dequeのような順序付きコレクションの取り扱いがさらに直感的になりました。新しいJavaバージョンを活用できる環境であれば、これらの機能も併せて習得することをお勧めします。

コメント