compareTo() と Comparable
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 44/87。
Comparable インターフェースを使用すると、オブジェクトが自身の自然な順序を定義できるようになります。このインターフェースを実装することで、クラスは Collections.sort() のようなメソッドを使用して自動的にソートされたり、TreeSet のようなソート済みコレクションに格納されたりすることが可能になります。
このインターフェースでは、単一のメソッド compareTo() を実装する必要があります。このメソッドは、現在のオブジェクトを別のオブジェクトと比較し、それらの相対的な順序を示す整数を返します:
- 負の値: このオブジェクトはもう一方のオブジェクトの前に配置されます
- ゼロ: 両方のオブジェクトは等しいです
- 正の値: このオブジェクトはもう一方のオブジェクトの後に配置されます
public class Person implements Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return this.age - other.age; // 年齢の昇順でソート
}
}実装されると、ソートは簡単になります:
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
Collections.sort(people); // 年齢順にソートされました: Bob, Alice文字列や他の Comparable フィールドを比較する場合、引き算を使用する代わりに、それらの compareTo() メソッドに委譲することができます:return this.name.compareTo(other.name);。このアプローチはより安全で、エッジケースを適切に処理します。
チャレンジ
簡単Comparable インターフェースを使用して、映画を評価順にソートする映画ランキングシステムを構築しましょう。自分自身を他の映画と比較する方法を知っている Movie クラスを作成し、評価の高い順から低い順への自動ソートを可能にします。
コードは2つのファイルに分けて構成します:
Movie.java: 他の映画と比較可能な、映画を表すクラスを作成します。Movie は3つのプライベートフィールドを持ちます:title(String)、director(String)、およびrating(double、0.0 から 10.0)。すべてのフィールドを初期化するコンストラクタと、それぞれのゲッターメソッドを含めてください。Movie クラスに
Comparable<Movie>を実装させ、compareTo()メソッドをオーバーライドします。映画は評価の 降順 (高い順) でソートされる必要があります。double 値を比較する際は、安全な比較のためにDouble.compare()を使用してください。降順ソートにするために順序を逆にすることを忘れないでください!toString()をオーバーライドして、次の形式で返すようにします:[title] by [director] - Rating: [rating]Main.java: 映画のリストを作成してソートし、Movie クラスを実際に動かしてみましょう。3つの映画の入力を受け取ります。各映画は個別の行にtitle,director,ratingの形式で入力されます。各行を解析して Movie オブジェクトを作成し、それらを
ArrayListに追加します。その後、Collections.sort()を使用してリストをソートします。Comparableの実装のおかげで、映画は自動的に評価順に並び変わります!ソート後、各映画を
toString()の形式で1行ずつ出力します。最も評価の高い映画が最初に表示されるはずです。
入力として、映画データを含む3行を受け取ります。各行の形式は title,director,rating です。
例えば、入力行は次のようになります:Inception,Christopher Nolan,8.8
Main ファイルで java.util.ArrayList、java.util.Collections、および java.util.Scanner をインポートすることを忘れないでください。Comparable を実装することで、追加のコンパレータを必要とせず、単一のメソッド呼び出しでカスタムオブジェクトをソートできることに注目してください!
チートシート
Comparable インターフェースを使用すると、オブジェクトが自動ソートのための自然な順序を定義できるようになります。
以下の値を返す compareTo() メソッドを実装します:
- 負の値: このオブジェクトが他のオブジェクトより前に来る
- ゼロ: 両方のオブジェクトが等しい
- 正の値: このオブジェクトが他のオブジェクトより後に来る
public class Person implements Comparable<Person> {
private int age;
@Override
public int compareTo(Person other) {
return this.age - other.age; // 年齢の昇順でソート
}
}Collections.sort() を使用してオブジェクトをソートします:
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
Collections.sort(people); // 年齢順にソートされる文字列を比較する場合は、その compareTo() メソッドに委譲します:
return this.name.compareTo(other.name);double 型を安全に比較するには、Double.compare() を使用します:
return Double.compare(this.rating, other.rating); // 昇順
return Double.compare(other.rating, this.rating); // 降順自分で試してみよう
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行を読み込む
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: Movie オブジェクトを格納するための ArrayList を作成する
// TODO: 各行を解析する (フォーマット: title,director,rating)
// Hint: 各パーツを分割するために split(",") を使用する
// Hint: rating には Double.parseDouble() を使用する
// TODO: Movie オブジェクトを作成し、リストに追加する
// TODO: Collections.sort() を使用してリストをソートする
// TODO: 各映画を出力する (1行に1つ)
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造7特殊メソッドとObjectクラス
toString() メソッドequals() と hashCode()clone() メソッドcompareTo() と ComparableComparator インターフェースまとめ - カスタムソート