Javaにおけるオブジェクトの比較とソート:ComparableとComparatorの活用

Javaにおいて、自作クラスのインスタンス同士を比較したり、リストや配列内でソートしたりするためには、適切なインターフェースを実装する必要があります。標準のequals()メソッドは等価判定を行いますが、大小関係の評価や順序付けにはComparableまたはComparatorを用います。

1. Comparableインターフェース(自然順序付け)

Comparableを実装することは、そのクラス自身に「自然な順序(デフォルトの並び順)」を持たせることを意味します。このインターフェースを実装したクラスのインスタンスは、Arrays.sort()Collections.sort()を引数なしで呼び出すだけでソート可能です。

実装すべきcompareTo(T o)メソッドは、自分自身と対象オブジェクトを比較し、負の数・0・正の数のいずれかを返します。

public class Employee implements Comparable<Employee> {
    private String name;
    private int salary;

    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee other) {
        // 給与で昇順に並べる
        return Integer.compare(this.salary, other.salary);
    }
}

2. Comparatorインターフェース(外部比較器)

Comparatorは、クラスのソースコードを修正せずに外部からソート順を定義したい場合に利用します。特に、サードパーティ製のライブラリに含まれるクラスや、複数の異なるソート順(名前順、給与順など)を切り替えたい場合に有効です。

import java.util.Comparator;

public class SalaryComparator implements Comparator<Employee> {
    @Override
    public int compare(Employee e1, Employee e2) {
        return Integer.compare(e1.getSalary(), e2.getSalary());
    }
}

// 利用例
// Arrays.sort(employees, new SalaryComparator());

3. 両者の比較と使い分け

両者の主な違いを整理すると以下の通りです。

  • Comparable (内部比較器): クラス設計時に「そのクラスが本来どう並ぶべきか」を決定する。実装はシンプルだが、ソースコードの変更が必要。
  • Comparator (外部比較器): 外部からソートのルールを指定する。既存のクラスを改変せずに、動的に異なるロジックを注入できる。

特にComparatorを使用する場合、汎用的な比較クラスを作成したり、Java 8以降であればラムダ式やComparator.comparingInt()のようなメソッドを使用して、より簡潔に記述することが推奨されます。

// Java 8以降の簡潔な書き方
import java.util.Arrays;
import java.util.Comparator;

Arrays.sort(employees, Comparator.comparingInt(Employee::getSalary));

タグ: Java Collections Sorting Interfaces

7月24日 20:01 投稿