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 Integer.compare(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);。这种方式更安全,也能妥善处理边界情况。对于 int 字段,优先使用 Integer.compare(a, b),而不是 a - b,因为极端值可能导致减法溢出。
挑战
简单让我们构建一个电影排名系统,使用 Comparable 接口按评分对电影排序。你将创建一个 Movie 类,让它知道如何与其他电影比较,从而自动按评分从高到低排序。
你将把代码分在两个文件中:
Movie.java:创建一个表示电影的类,使其可以与其他电影比较。Movie 有三个私有字段:title(String)、director(String)和rating(double,范围从 0.0 到 10.0)。添加一个用于初始化所有字段的构造函数,以及每个字段对应的 getter 方法。让 Movie 类实现
Comparable<Movie>,并重写compareTo()方法。电影应按评分降序排列(评分最高的排在最前面)。比较 double 值时,使用Double.compare()进行安全比较:记得在降序排序时反转顺序!重写
toString(),使其返回:[title] by [director] - Rating: [rating]Main.java:创建电影列表并对其排序,让你的 Movie 类发挥作用。你会收到三部电影的输入,每部电影占一行,格式为:title,director,rating解析每一行以创建 Movie 对象,将它们添加到一个
ArrayList中,然后使用Collections.sort()对列表排序。由于实现了Comparable,电影会自动按评分排列!排序后,按照
toString()格式逐行打印每部电影。评分最高的电影应排在最前面。
你会收到三行输入,每行包含一部电影的数据,格式为:title,director,rating
例如,输入行可能如下所示:Inception,Christopher Nolan,8.8
记得在 Main 文件中导入 java.util.ArrayList、java.util.Collections 和 java.util.Scanner。注意,实现 Comparable 后,只需调用一个方法就能对自定义对象排序:不需要额外的比较器!
亲手试试
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);
// 读取三行电影数据
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO:创建一个 ArrayList 来存储 Movie 对象
// TODO:解析每一行(格式:title,director,rating)
// 提示:用 split(",") 分隔各部分
// 提示:用 Double.parseDouble() 处理评分
// TODO:创建 Movie 对象并将它们添加到列表中
// TODO:用 Collections.sort() 对列表排序
// TODO:输出每部电影(每行一部)
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
7特殊方法与 Object 类
toString() 方法equals() 和 hashCode()clone() 方法compareTo() 和 ComparableComparator 接口回顾:自定义排序自己练习: Java 在线编译器