JAVA——ComparableインタフェースとComparatorインタフェースの違い
JAVA——ComparableインタフェースとComparatorインタフェースの違いが正数を返すと、 負数を返すと、 がゼロに戻ると、
両者のつながり
事例の理解を深める
比較用カスタム
上記の
デバッグコード:
実行結果は次のとおりです.
拡張
一度だけソートする場合は、コンパレータを定義せずに匿名の内部クラスを直接使用できます.
上記の書き方は依然として煩雑で複雑であることは明らかであり、Lambda式を利用して簡略化することができる.
さらに簡略化(パラメータタイプを削除):
最終的に方法を適用して簡略化する(同時に優先比較量が等しい場合の継続比較根拠を定義する):
逆順序が必要な場合は、次の手順に従います.
Comparable
インタフェースComparable
はソートインタフェースです.1つのクラスがComparable
インタフェースを実装し、すなわち、クラスがcompareTo
メソッドを実装したことを表す場合、このメソッドは、クラスのオブジェクトの比較規則(2つのオブジェクトが「サイズ」をどのように比較するか)を規定する.クラスは、o1.compareTo(o2)
メソッドを実装することによって、o1
およびo2
のサイズを比較する.o1
がo2
より大きいことを意味する.o1
がo2
より小さいことを意味する.o1
がo2
に等しいことを意味する.Comparator
インタフェースComparator
はコンパレータインターフェースである.特定のオブジェクトの順序を制御するだけで、クラス自体がソートをサポートしていない(すなわち、Comparable
インタフェースが実装されていない)場合、比較器(すなわち、クラスに関するComparator
インタフェース実装クラス)を確立することによってソートを行うことができる.比較器は、上記のcompare(T o1, T o2)
の方法と同様の原理を有する方法o1.compareTo(o2)
を実装する必要があり、ここでは説明しない.両者のつながり
Comparable
インタフェースは、内部比較器に相当するデフォルトのソートを表す自己クラスで実装される.Comparator
インタフェースは、外部比較器に相当するクラス外で実現される比較器である.事例の理解を深める
比較用カスタム
Student
クラス:public class Student implements Comparable<Student> {
private String name;
private int grade;
public Student() {
}
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
public void setName(String name) {
this.name = name;
}
public void setGrade(int grade) {
this.grade = grade;
}
public String getName() {
return name;
}
public int getGrade() {
return grade;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", grade=" + grade +
'}';
}
@Override
@Override
public int compareTo(Student o) {
return this.getGrade() > o.getGrade() ? 1 : this.getGrade() < o.getGrade() ? -1 : this.getName().compareTo(o.getName());
}
}
上記の
Student
クラスはComparable
インタフェースを実現し、デフォルトのソートがあり、デバッグコードは以下の通りである.public class Main {
public static void main(String[] args) {
List<Student> arr = new ArrayList<>();
arr.add(new Student("John", 100));
arr.add(new Student("Bob", 75));
arr.add(new Student("Alice", 100));
arr.add(new Student("Jake", 90));
System.out.println(arr);
System.out.println("------------------------");
Collections.sort(arr); //
System.out.println(arr);
}
}
Compartor
インタフェースを実装する別の比較器は、以下のように定義される.public class StuCompartor implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.getGrade() > o2.getGrade() ? 1 : o1.getGrade() < o2.getGrade() ? -1 : o1.getName().compareTo(o2.getName());
}
}
デバッグコード:
public class StuMain {
public static void main(String[] args) {
List<Student> arr = new ArrayList<>();
arr.add(new Student("John", 100));
arr.add(new Student("Bob", 75));
arr.add(new Student("Alice", 100));
arr.add(new Student("Jake", 90));
System.out.println(arr);
System.out.println("------------------------");
Collections.sort(arr, new StuCompartor());//
System.out.println(arr);
}
}
実行結果は次のとおりです.
[Student{
name='John', grade=100}, Student{
name='Bob', grade=75}, Student{
name='Alice', grade=100}, Student{
name='Jake', grade=90}]
------------------------
[Student{
name='Bob', grade=75}, Student{
name='Jake', grade=90}, Student{
name='Alice', grade=100}, Student{
name='John', grade=100}]
拡張
一度だけソートする場合は、コンパレータを定義せずに匿名の内部クラスを直接使用できます.
Collections.sort(arr, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getGrade() > o2.getGrade() ? 1 : o1.getGrade() < o2.getGrade() ? -1 : o1.getName().compareTo(o2.getName());
}
});
上記の書き方は依然として煩雑で複雑であることは明らかであり、Lambda式を利用して簡略化することができる.
Collections.sort(arr, (Student o1, Student o2) -> {
return o1.getGrade() > o2.getGrade() ? 1 : o1.getGrade() < o2.getGrade() ? -1 : o1.getName().compareTo(o2.getName());
});
さらに簡略化(パラメータタイプを削除):
Collections.sort(arr, (o1, o2) -> {
return o1.getGrade() > o2.getGrade() ? 1 : o1.getGrade() < o2.getGrade() ? -1 : o1.getName().compareTo(o2.getName());
});
最終的に方法を適用して簡略化する(同時に優先比較量が等しい場合の継続比較根拠を定義する):
Collections.sort(arr, comparing(Student::getGrade)
.thenComparing(Student::getName));
逆順序が必要な場合は、次の手順に従います.
Collections.sort(arr, comparing(Student::getGrade)
.reversed()
.thenComparing(Student::getName));