【Java学習|実務向け】Java 21の隠れた名機能:SequencedSetでコレクション操作を直感的にする

導入

Java 21で導入された「Sequenced Collections」は、長年Java開発者を悩ませてきた「順序付きコレクションへのアクセス」という課題を根本から解決しました。これまで、LinkedHashSetなどの順序を保持するセットであっても、先頭や末尾の要素にアクセスするには、イテレータを回したり、一度リストに変換したりする必要がありました。SequencedSetを活用することで、これらの冗長なコードを排除し、可読性と保守性の高いコードを実現できます。

基礎知識

SequencedSetは、java.util.SequencedCollectionインターフェースを継承したSetの一種です。最大の特徴は、その要素が「遭遇順序(encounter order)」を持っていることです。
これまで、Setインターフェースには「順序」という概念が希薄でした。しかし、LinkedHashSetのように順序を保証する実装クラスに対しても、言語仕様として統一されたアクセス方法がありませんでした。SequencedSetは、先頭(First)と末尾(Last)に対して、要素の追加、取得、削除を行うメソッドを標準化しました。これにより、スタックやキューのような振る舞いをSetでも自然に扱えるようになりました。

実装/解決策

SequencedSetを利用するには、Java 21以上の環境でLinkedHashSetなどの実装クラスを使用します。主な操作メソッドには以下があります。

・addFirst(E e): 先頭に要素を追加
・addLast(E e): 末尾に要素を追加
・getFirst(): 先頭の要素を取得
・getLast(): 末尾の要素を取得
・removeFirst(): 先頭の要素を削除して返す
・removeLast(): 末尾の要素を削除して返す
・reversed(): 順序を逆にしたビューを返す

これらを使うことで、これまでCollections.reverse()を呼び出したり、手動で反復処理を書いていたロジックが、一行で記述可能になります。

サンプルプログラム

以下に、SequencedSetを活用した実用的なサンプルコードを示します。

import java.util.LinkedHashSet;
import java.util.SequencedSet;

public class SequencedSetExample {
    public static void main(String[] args) {
        // LinkedHashSetはJava 21からSequencedSetを実装しています
        SequencedSet<String> orderedSet = new LinkedHashSet<>();

        // 要素の追加
        orderedSet.add("Java");
        orderedSet.add("Python");
        orderedSet.add("Go");

        // 先頭への追加
        orderedSet.addFirst("Rust");
        
        // 末尾の取得
        System.out.println("末尾の要素: " + orderedSet.getLast()); // 出力: Go

        // 順序を反転させて処理(元のコレクションには影響しません)
        System.out.println("逆順の要素:");
        orderedSet.reversed().forEach(System.out::println);

        // 先頭要素の安全な削除
        String removed = orderedSet.removeFirst();
        System.out.println("削除された先頭要素: " + removed);
    }
}

応用・注意点

現場での開発において注意すべき点は、「すべてのSetが順序を持つわけではない」ということです。HashSetのような順序を保証しない実装クラスに対してSequencedSetのメソッドを呼び出すと、UnsupportedOperationExceptionが発生します。

また、reversed()メソッドが返すのは「コピー」ではなく「ビュー(View)」であるという点も重要です。ビューに対する変更は元のコレクションにも反映されますが、元のコレクションの構造が変更されると、ビュー側の動作が定義されない場合があります。

レガシーなコードをJava 21に移行する際は、まずはLinkedHashSetを使用している箇所を見つけ、Listへのキャストや面倒なイテレータ操作を行っているロジックを、SequencedSetのメソッドに置き換えることから始めてみてください。コードの意図が明確になり、バグの混入リスクを大幅に下げることができます。

コメント

タイトルとURLをコピーしました