Comparable和Comparator
文章目录
- 使用 Comparable
- 使用 Comparator
- 传统匿名内部类
- Lambda 表达式
- 链式调用
- 总结
在 Java 中,自定义类的排序规则需要通过实现 Comparable 接口或提供 Comparator 来定义。以下是两种主要方式的详细说明:
使用 Comparable
让类本身实现 Comparable<T> 接口,并覆写 compareTo(T o) 方法,定义默认排序规则。
import java.util.Arrays;class Student implements Comparable<Student> {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "[" + this.name + ":" + this.score + "]";}@Overridepublic int compareTo(Student o) {// 按分数降序排序,如果分数相同则按姓名升序int scoreDiff = o.score - this.score;if (scoreDiff != 0) {return scoreDiff;}return this.name.compareTo(o.name);}
}public class Test {public static void main(String[] args) {Student[] students = new Student[] {new Student("张三", 95),new Student("李四", 96),new Student("王五", 97),new Student("赵六", 92),};Arrays.sort(students);System.out.println(Arrays.toString(students));}
}
为了进一步加深对接口的理解, 我们可以尝试自己实现一个 sort 方法来完成刚才的排序过程(使用冒泡排序)
import java.util.Arrays;class Student implements Comparable<Student> {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "[" + this.name + ":" + this.score + "]";}@Overridepublic int compareTo(Student o) {// 按分数降序排序,如果分数相同则按姓名升序int scoreDiff = o.score - this.score;if (scoreDiff != 0) {return scoreDiff;}return this.name.compareTo(o.name);}
}public class Test {public static void sort(Comparable[] array) {for (int i = 0; i < array.length - 1; i++) {for (int j = 0; j < array.length - 1 - i; j++) {if (array[j].compareTo(array[j+1]) > 0) {Comparable tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;}}}}public static void main(String[] args) {Student[] students = new Student[] {new Student("张三", 95),new Student("李四", 96),new Student("王五", 97),new Student("赵六", 92),};sort(students);System.out.println(Arrays.toString(students));}
}
使用 Comparator
不修改原类,通过创建 Comparator<T> 实现类或使用 Lambda 表达式定义临时排序规则。
传统匿名内部类
import java.util.Arrays;
import java.util.Comparator;class Student {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "[" + this.name + ":" + this.score + "]";}// Getter方法用于访问私有字段public String getName() { return name; }public int getScore() { return score; }
}public class Test {public static void main(String[] args) {Student[] students = new Student[] {new Student("张三", 95),new Student("李四", 96),new Student("王五", 97),new Student("赵六", 92),};// 使用Comparator实现降序排序Comparator<Student> comparator = new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {return Integer.compare(s2.getScore(), s1.getScore()); // 手动实现降序}};// 传入Comparator进行排序Arrays.sort(students, comparator);System.out.println(Arrays.toString(students));}
}
Lambda 表达式
import java.util.Arrays;
import java.util.Comparator;class Student {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "[" + this.name + ":" + this.score + "]";}// Getter方法用于访问私有字段public String getName() { return name; }public int getScore() { return score; }
}public class Test {public static void main(String[] args) {Student[] students = new Student[] {new Student("张三", 95),new Student("李四", 96),new Student("王五", 97),new Student("赵六", 92),};// 使用Comparator实现降序排序Comparator<Student> comparator = (s1, s2) -> s2.getScore() - s1.getScore();// 传入Comparator进行排序Arrays.sort(students, comparator);System.out.println(Arrays.toString(students));}
}
链式调用
import java.util.Arrays;
import java.util.Comparator;class Student {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "[" + this.name + ":" + this.score + "]";}// Getter方法用于访问私有字段public String getName() { return name; }public int getScore() { return score; }
}public class Test {public static void main(String[] args) {Student[] students = new Student[] {new Student("张三", 95),new Student("李四", 96),new Student("王五", 97),new Student("赵六", 92),};// 使用Comparator实现降序排序Comparator<Student> scoreComparator = Comparator.comparingInt(Student::getScore).reversed();// 传入Comparator进行排序Arrays.sort(students, scoreComparator);System.out.println(Arrays.toString(students));}
}
Student::getScore
是一种简洁的函数式语法,等价于 lambda 表达式(Student s) -> s.getScore()
。- 由于
getScore()
返回 int,符合 ToIntFunction 接口的要求。
总结
- Comparable让类自身实现排序规则,适用于类的默认排序逻辑;Comparator在外部定义排序规则,不修改原类。可通过 Lambda 简化实现。适用于临时排序或多种排序方式。
- Comparable 是通过重写 compareTo 方法实现排序的,而 Comparator 是通过重写 compare 方法实现排序的
- 侵入性:实现Comparable接口会对类产生侵入,因为要修改类的定义;实现Comparator接口则不会影响类的定义,能在不修改类的情况下实现不同的排序规则。
- 使用灵活性:Comparable接口只能有一种自然排序规则;Comparator接口可以创建多个不同的比较器,实现多种排序规则。