Comparableは、オブジェクトのクラス自体によって実装されるインターフェースです。自然なソート順を定義するcompareTo()メソッドを1つ定義します。
Comparatorは、compare(o1, o2)メソッドを実装する独立したインターフェースです。クラスのコードを変更することなく、複数のソート方法を定義することができます。
使用するタイミング:
例:
// Comparable class Student implements Comparable<Student> { String name; int grade; public int compareTo(Student other) { return this.grade - other.grade; } } // Comparator Comparator<Student> byName = new Comparator<Student>() { public int compare(Student s1, Student s2) { return s1.name.compareTo(s2.name); } }; List<Student> students = ...; Collections.sort(students); // gradeによるソート Collections.sort(students, byName); // nameによるソート
Comparableを実装していないオブジェクトのListをComparatorなしでソートできますか?
回答: いいえ。クラスがComparableを実装しておらず、明示的にComparatorが渡されていない場合、コレクションのソートを試みるとClassCastExceptionがスローされます。
例:
class Animal {} List<Animal> animals = ...; Collections.sort(animals); // Comparableがない場合、ClassCastException
歴史
インベントリプロジェクトで、ItemクラスにComparableを実装するのを忘れました。Collections.sort(items)によるソートを試みた結果、compareTo()メソッドがないため、アプリケーションがClassCastExceptionで繰り返しクラッシュしました。
歴史
生徒の評価計算サービスで、開発者はgradeフィールドでの比較をcompareTo()メソッド内にのみ実装しました。後に名前や生年月日でソートする必要があったが、クラスのコードが補助メソッドで膨れ上がり、異なるComparatorを使用する代わりにcompareTo()で複雑なロジックを避けることができませんでした。
歴史
オンライン注文の製品で、日付で注文をソートするためにComparatorをラムダ式で使用しようとしましたが、日付がnullになる可能性を考慮するのを忘れました。その結果、納品日のない注文のソート時に予期しないNullPointerExceptionがプロダクションで発生しました。