導入
JavaのMapインターフェースは長年「順序を保持しない」ことが前提でした。LinkedHashMap等を使えば順序は維持できましたが、標準APIとして「最初や最後の要素を取得・削除する」メソッドは用意されておらず、冗長なコードを書いていた経験はありませんか?Java 21で導入されたSequencedMapは、順序を意識した操作を標準化し、コードの可読性と安全性を劇的に向上させます。
基礎知識
SequencedMapは、Java 21の「Sequenced Collections」という枠組みの一部です。これは、要素に「最初(First)」と「最後(Last)」という概念を持つコレクションを統一的に扱うインターフェースです。Mapにおいて、挿入順序が保持されている場合にのみ、このインターフェースが適用されます。これにより、これまでLinkedHashMap等にキャストして行っていた操作が、型安全かつ直感的に行えるようになりました。
実装/解決策
SequencedMapが提供する強力なメソッドは以下の通りです。
・putFirst(K, V) / putLast(K, V): 先頭または末尾に要素を追加。
・firstEntry() / lastEntry(): 先頭または末尾の要素を取得。
・pollFirstEntry() / pollLastEntry(): 先頭または末尾の要素を取り出して削除。
・reversed(): 順序を反転させたビューを返す。
これらを使うことで、LRUキャッシュのような構造や、最新のログだけを保持するような実装が非常にシンプルになります。
サンプルプログラム
以下のコードは、SequencedMapの機能を活用した実用的な例です。
import java.util.LinkedHashMap;
import java.util.SequencedMap;
public class SequencedMapDemo {
public static void main(String[] args) {
// LinkedHashMapはSequencedMapを実装しています
SequencedMap map = new LinkedHashMap<>();
// 要素の追加
map.put("A", "Apple");
map.put("B", "Banana");
map.put("C", "Cherry");
// 先頭に要素を追加
map.putFirst("Z", "Zero");
// 最後を取得
System.out.println("最後: " + map.lastEntry()); // C=Cherry
// 最初を取り出して削除
var first = map.pollFirstEntry();
System.out.println("取り出した最初: " + first); // Z=Zero
// 順序を逆にして出力
System.out.println("逆順:");
map.reversed().forEach((k, v) -> System.out.println(k + ": " + v));
}
}
応用・注意点
注意点として、すべてのMapがSequencedMapを実装しているわけではありません。HashMapなどは順序を保証しないため、SequencedMapとして扱うことはできません。また、nullキーやnull値の扱いについては、実装クラス(LinkedHashMapなど)の仕様に依存するため、使用する実装クラスのドキュメントを必ず確認してください。
現場での活用としては、特に「最新のN件を保持する」といったロジックを実装する際、従来のようなIteratorを介した複雑な操作を排除できるため、バグの温床を減らすことができます。Java 21へ移行済みであれば、ぜひ積極的に活用してみてください。

コメント