Menu
CoddyTech

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,因为极端值可能导致减法溢出。

challenge icon

挑战

简单

让我们构建一个电影排名系统,使用 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:输出每部电影(每行一部)
    }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Java 在线编译器