Comparator インターフェース
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 45/87。
Comparableはクラスの自然順序を定義しますが、オブジェクトを異なる方法で並べ替える必要がある場合もあります。Comparatorインターフェースを使うと、元のクラスを変更せずに、個別の比較ロジックを作成できます。
Comparatorは、同じ型の2つのオブジェクトを比較する外部オブジェクトです。複数の並べ替えオプションが必要な場合や、クラス自体を変更できない場合に便利です。
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}その後、comparatorをソートメソッドに渡せます。
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));
Collections.sort(people, new NameComparator()); // 名前でソート
Collections.sort(people, new AgeComparator()); // 年齢でソート簡潔なコードにするには、Comparator は関数型インターフェースなので、ラムダ式を使用できます。
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));主な違いは次のとおりです。Comparableは比較されるクラスによって実装され、1つの自然順序を定義します。一方、Comparatorは別個のクラスであり、無制限のカスタム順序を定義できます。
チャレンジ
簡単Comparator interface の力を示す、Employee の並べ替えシステムを構築しましょう。Employee クラス自体を変更せずに、salary と name によって Employee を異なる方法で並べ替える複数の comparator を作成します。
コードを4つのファイルに整理します。
Employee.java: Employee を表すクラスを作成し、3つの private な fields、name(String)、department(String)、salary(double)を定義します。すべての fields を初期化する constructor と、それぞれの getter メソッドを含めます。toString()をオーバーライドし、次を返すようにします:[name] ([department]) - $[salary]SalaryComparator.java: salary の descending order(給与が highest の Employee が先)で Employee を並べ替える comparator を作成します。Comparator<Employee>interfaceとそのcompare()メソッドを Implement します。salary の値を安全に比較するためにDouble.compare()を使用します。NameComparator.java: name のアルファベット順に ASCENDING(A から Z)で Employee を並べ替える別の comparator を作成します。Comparator<Employee>を Implement し、比較には String のcompareTo()メソッドを使用します。Main.java: Employee の list を作成し、comparator を使用して並べ替えることで、すべてをまとめます。3人の Employee の input を受け取ります。それぞれ別の line に、次の format で入力されます:name,department,salaryEmployee の
ArrayListを作成し、次の2つの並べ替え方法を示します。- まず、
SalaryComparatorを使用して salary で並べ替え、それぞれの Employee を出力します - empty line を出力します
- 次に、
NameComparatorを使用して name で並べ替え、それぞれの Employee を出力します
- まず、
Employee のデータを含む3本の input line を受け取ります。それぞれ次の format です: name,department,salary
たとえば、input line は次のようになります: Alice,Engineering,75000.0
comparator ファイルでは java.util.Comparator を、Main ファイルでは java.util.ArrayList、java.util.Collections、java.util.Scanner を import することを忘れないでください。comparator によって、外部で複数の並べ替え戦略を定義できることに注目してください。Employee クラスは、自分がどのように並べ替えられるかについて何も知る必要がありません。
自分で試してみよう
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 入力から3人の従業員を読み取る
// 各行の形式: name,department,salary
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: 各行を解析してEmployeeオブジェクトを作成する
// ヒント: 値を区切るにはsplit(",")を使用する
// TODO: 従業員のArrayListを作成し、3つすべてを追加する
// TODO: SalaryComparatorを使用して給与でソートし、各従業員を出力する
// ヒント: Collections.sort(list, comparator)を使用する
// TODO: 空行を出力する
// TODO: NameComparatorを使用して名前でソートし、各従業員を出力する
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造7特殊メソッドとObjectクラス
toString() メソッドequals() と hashCode()clone() メソッドcompareTo() と ComparableComparator インターフェースまとめ - カスタムソート自分で練習してみよう: Javaオンラインコンパイラ