導入
業務システムにおいて、リストのソート処理は避けて通れません。しかし、複数のフィールドで優先順位をつけてソートする場合、if文を重ねた複雑なComparatorを記述していませんか?そのコードは非常に読みづらく、バグの温床になりがちです。Java 8から導入されたComparatorのメソッドチェーンを活用することで、宣言的で読みやすく、かつ保守性の高いソート処理を実現できます。本稿では、この「Chained Comparators」の活用術を解説します。
基礎知識
Comparatorは、オブジェクトの順序を定義するための関数型インターフェースです。Java 8以降、Comparatorインターフェースにはデフォルトメソッドや静的メソッドが追加され、比較ロジックを連結(チェーン)できるようになりました。
特に重要なのが「thenComparing」メソッドです。これは「まずこの条件で比較し、同値であれば次の条件で比較する」という優先順位を、メソッドチェーンで表現できる仕組みです。これにより、従来の複雑なネスト構造を排除し、コードの意図を直感的に記述できるようになります。
実装/解決策
Chained Comparatorsを実装する際は、まず比較のキーとなるフィールドを「Comparator.comparing(…)」で指定します。次に、第2、第3の優先順位を「thenComparing(…)」でつなげていきます。
また、nullの取り扱いについても「nullsFirst()」や「nullsLast()」といった便利なヘルパーメソッドが用意されており、これらを組み合わせることで、null安全なソート定義を簡潔に記述することが可能です。
サンプルプログラム
以下は、ユーザー情報を「部署名(昇順)」→「年齢(降順)」→「名前(昇順)」でソートする実用的な例です。
import java.util.;
public class UserSortExample {
public static void main(String[] args) {
List
new User(“佐藤”, “営業部”, 30),
new User(“鈴木”, “開発部”, 25),
new User(“田中”, “営業部”, 25)
);
// Chained Comparatorsを用いたソート定義
Comparator
.comparing(User::getDepartment) // 1. 部署名で昇順
.thenComparing(User::getAge, Comparator.reverseOrder()) // 2. 年齢で降順
.thenComparing(User::getName); // 3. 名前で昇順
users.sort(userComparator);
users.forEach(System.out::println);
}
}
class User {
private String name;
private String department;
private int age;
public User(String name, String department, int age) {
this.name = name;
this.department = department;
this.age = age;
}
public String getName() { return name; }
public String getDepartment() { return department; }
public int getAge() { return age; }
@Override
public String toString() {
return String.format(“%s (%s, %d歳)”, name, department, age);
}
}
応用・注意点
1. パフォーマンスへの配慮
Comparatorをソートのたびにインスタンス化すると、頻繁に呼び出されるメソッド内ではGCの負荷になる可能性があります。固定的なソート順であれば、クラスのstatic定数として定義しておくことを推奨します。
2. 型推論の限界
「comparing()」メソッドは型推論を使用していますが、複雑なネストやラムダ式が絡むとコンパイルエラーになることがあります。その場合は、明示的に型を指定するか、メソッド参照を活用してシンプルに記述してください。
3. 比較対象のNullチェック
フィールドがnullを許容する場合、単純な「User::getName」ではNullPointerExceptionが発生します。「Comparator.nullsLast(Comparator.naturalOrder())」などのNull系ユーティリティを適切に組み合わせて、堅牢なソート処理を構築しましょう。

コメント