彻底搞懂 Comparable 和 Comparator

✅ 一句话区分

  • Comparable一个类 自己具备"可比较性"------实现 compareTo 方法,表示默认排序方式。
  • Comparator外部定义 比较逻辑------实现 compare 方法,用来指定多个排序规则(或临时排序规则)。

一、Comparable:自然排序,类内定义

特点

  • 属于 "类自身"定义排序规则
  • 实现 Comparable<T> 接口,需要重写 compareTo() 方法。
  • 只能有一个排序规则(因为在类里写死了)。

示例:定义一个 Student 类,按年龄升序排序

csharp 复制代码
import java.util.*;
​
public class Student implements Comparable<Student> {
​
    // 学生姓名
    private String name;
​
    // 学生年龄
    private int age;
​
    // 构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    // 获取姓名
    public String getName() {
        return name;
    }
​
    // 获取年龄
    public int getAge() {
        return age;
    }
​
    // 重写 Comparable 接口的 compareTo 方法
    @Override
    public int compareTo(Student other) {
        // 按年龄升序排列
        return this.age - other.age;
    }
​
    // 重写 toString 方便打印
    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
​
    // 测试代码
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("Alice", 23));
        list.add(new Student("Bob", 20));
        list.add(new Student("Charlie", 22));
​
        // 按照 compareTo 排序
        Collections.sort(list);
​
        // 打印结果
        System.out.println("按年龄升序(Comparable):");
        for (Student s : list) {
            System.out.println(s);
        }
    }
}

输出

scss 复制代码
按年龄升序(Comparable):
Bob (20)
Charlie (22)
Alice (23)

Collections.sort(List) 使用说明

Collections.sort支持两种传参: 1, 直接传入集合对象; 2, 传入集合对象和 Comparator 实现;

当调用 Collections.sort(list), 底层会判断你传入的 list 中元素是否实现了 Comparable 接口:

  • 如果实现了,就自动使用每个元素的 compareTo() 方法进行比较排序;
  • 如果没有实现,会抛出异常(ClassCastException);
  • 如果你调用的是 Collections.sort(list, comparator),就会使用你传入的 Comparatorcompare() 方法,而不是 compareTo()

二、Comparator:定制排序,类外定义

特点

  • 可以不修改类本身,就能排序。
  • 更灵活:可以定义多个排序逻辑。
  • 实现 Comparator<T> 接口,重写 compare(T o1, T o2) 方法。

示例

使用 Comparator 实现不同排序逻辑

csharp 复制代码
import java.util.*;
​
public class StudentComparatorDemo {
​
    public static class Student {
        private String name;
        private int age;
​
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
​
        public String getName() {
            return name;
        }
​
        public int getAge() {
            return age;
        }
​
        @Override
        public String toString() {
            return name + " (" + age + ")";
        }
    }
​
    // 定义按姓名升序排序的比较器
    public static class NameComparator implements Comparator<Student> {
        @Override
        public int compare(Student s1, Student s2) {
            // 按名字字母升序排列
            return s1.getName().compareTo(s2.getName());
        }
    }
​
    // 定义按年龄降序排序的比较器
    public static class AgeDescComparator implements Comparator<Student> {
        @Override
        public int compare(Student s1, Student s2) {
            // 年龄从大到小
            return s2.getAge() - s1.getAge();
        }
    }
​
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("Alice", 23));
        list.add(new Student("Bob", 20));
        list.add(new Student("Charlie", 22));
​
        // 按姓名升序排序
        Collections.sort(list, new NameComparator());
        System.out.println("按姓名升序(Comparator):");
        for (Student s : list) {
            System.out.println(s);
        }
​
        // 按年龄降序排序
        Collections.sort(list, new AgeDescComparator());
        System.out.println("按年龄降序(Comparator):");
        for (Student s : list) {
            System.out.println(s);
        }
    }
}

三、ComparableComparator 总结对比表格

特性 Comparable Comparator
所在位置 类内部实现(implements 类外定义(独立类或匿名类或 Lambda)
方法名 compareTo(T o) compare(T o1, T o2)
是否可定义多个规则 否,只能有一个实现 是,可以有多个 Comparator 实现
是否破坏原类封装 是,需要修改类代码 否,不需要修改类代码
使用场景 类默认排序方式 临时排序、多个排序条件
推荐方式 只需要一种排序时使用 推荐使用,灵活、解耦

四、使用 Lambda 表达式简化 Comparator(Java 8+)

less 复制代码
Collections.sort(list, (s1, s2) -> s1.getName().compareTo(s2.getName()));

或者使用 List.sort() 方法:

less 复制代码
list.sort(Comparator.comparing(Student::getName));

五、结论:如何选用?

  • 需要类本身支持排序(默认排序) ➜ 实现 Comparable
  • 外部控制排序逻辑(灵活多样) ➜ 使用 Comparator
相关推荐
郑州光合科技余经理41 分钟前
PHP构建:支撑欧美澳市场的同城生活服务平台开发
java·开发语言·数据库·uni-app·php·排序算法·生活
超级大只老咪8 小时前
数组相邻元素比较的循环条件(Java竞赛考点)
java
小浣熊熊熊熊熊熊熊丶8 小时前
《Effective Java》第25条:限制源文件为单个顶级类
java·开发语言·effective java
毕设源码-钟学长8 小时前
【开题答辩全过程】以 公交管理系统为例,包含答辩的问题和答案
java·eclipse
啃火龙果的兔子8 小时前
JDK 安装配置
java·开发语言
星哥说事8 小时前
应用程序监控:Java 与 Web 应用的实践
java·开发语言
写写闲篇儿8 小时前
微软面试之白板做题
面试·职场和发展
派大鑫wink8 小时前
【JAVA学习日志】SpringBoot 参数配置:从基础到实战,解锁灵活配置新姿势
java·spring boot·后端
xUxIAOrUIII9 小时前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home9 小时前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法