【Java学習|実務向け】Java 8以降のList直接ソート:List.sort(Comparator)による効率的な実装術

導入

Java 8以前、リストをソートするためには「Collections.sort(list)」というユーティリティクラスを経由する必要がありました。しかし、Java 8からListインターフェースに直接「sort」メソッドが追加されたことで、より直感的かつ簡潔にソートを行えるようになりました。本記事では、このList.sort(Comparator)の仕組みと、実務で役立つ実践的な使い方を解説します。

基礎知識

Javaにおけるソートは、比較のルールを定義する「Comparator」インターフェースを利用します。Java 8以降、Comparatorは関数型インターフェースとなり、ラムダ式やメソッド参照を用いて非常に短く記述できるようになりました。List.sortメソッドは、呼び出し元のリストそのものを並び替える「破壊的」なメソッドであり、新しいリストを生成せずメモリ効率が良いのが特徴です。

実装/解決策

実務では、単なる昇順・降順だけでなく、複数の条件を組み合わせたソートが頻繁に求められます。Comparator.comparing()やthenComparing()を組み合わせることで、読みやすく堅牢なコードを構築できます。

サンプルプログラム

以下のコードは、ユーザーオブジェクトを「年齢」で昇順ソートし、年齢が同じ場合は「名前」でソートする実用的な例です。

import java.util.;

public class SortExample {
    public static void main(String[] args) {
        List<User> users = new ArrayList<>(Arrays.asList(
            new User("佐藤", 30),
            new User("鈴木", 25),
            new User("田中", 30)
        ));

        // 1. 年齢で昇順、同じ年齢なら名前で昇順にソート
        users.sort(Comparator.comparingInt(User::getAge)
                             .thenComparing(User::getName));

        // 結果の確認
        users.forEach(System.out::println);
    }
}

class User {
    private String name;
    private int age;

    public User(String name, int age) { this.name = name; this.age = age; }
    public String getName() { return name; }
    public int getAge() { return age; }
    @Override
    public String toString() { return name + "(" + age + ")"; }
}

応用・注意点

1. 不変リスト(Immutable List)への注意:
List.of()などで作成した不変リストに対してsort()を呼び出すと、UnsupportedOperationExceptionが発生します。ソートが必要な場合は、new ArrayList<>(list)のように、一度可変なリストに変換してから実行してください。

2. null値の取り扱い:
リスト内にnullが含まれている場合、通常のComparatorはNullPointerExceptionを引き起こします。Comparator.nullsFirst()やnullsLast()を活用して、nullの扱いを明示的に定義するのが現場での定石です。

3. Sequenced Collectionsとの併用:
Java 21から導入されたSequenced Collections(ListやLinkedHashSet等)では、先頭や末尾へのアクセスが容易になっています。ソート済みのリストに対して、これらの新しいインターフェースを活用すると、さらに柔軟なデータ操作が可能になります。

コメント

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