Comparable 和 Comparator异同

1. 定义

Comparable
  • :java.lang
  • 定义:一个接口,定义在类内部,表示该类对象具有自然排序能力。
  • 方法:int compareTo(T o),比较当前对象与参数对象的大小。
  • 特点:需要被比较的类本身实现该接口。
Comparator
  • :java.util
  • 定义:一个独立接口,用于定义外部比较逻辑,不要求被比较的类修改。
  • 方法:int compare(T o1, T o2),比较两个对象的大小。
  • 特点:通常作为外部比较器传递给排序方法或集合。

2. 主要区别

特性ComparableComparator
位置类内部实现外部定义,通常独立类或 Lambda
方法compareTo(T o)compare(T o1, T o2)
侵入性修改目标类(侵入式)不修改目标类(非侵入式)
使用场景定义类的自然排序提供灵活的自定义排序
实例数量一个类只能有一个自然顺序可为同一类定义多个比较器
典型使用String、Integer 等内置类的排序集合排序(如 Collections.sort)

3. 代码示例

Comparable 示例

定义自然排序(如按年龄排序):

class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.age, other.age); // 按年龄升序
    }

    @Override
    public String toString() {
        return "Student{name='" + name + "', age=" + age + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        TreeSet<Student> set = new TreeSet<>();
        set.add(new Student("张三", 20));
        set.add(new Student("李四", 18));
        set.add(new Student("王五", 22));
        System.out.println(set); // 按年龄排序
    }
}

输出

[Student{name='李四', age=18}, Student{name='张三', age=20}, Student{name='王五', age=22}]
Comparator 示例

外部定义多种排序规则

import java.util.*;

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 "Student{name='" + name + "', age=" + age + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        // 按年龄排序
        Comparator<Student> ageComparator = (s1, s2) -> Integer.compare(s1.getAge(), s2.getAge());
        TreeSet<Student> set1 = new TreeSet<>(ageComparator);
        set1.add(new Student("张三", 20));
        set1.add(new Student("李四", 18));
        set1.add(new Student("王五", 22));
        System.out.println("按年龄排序: " + set1);

        // 按姓名排序
        Comparator<Student> nameComparator = Comparator.comparing(Student::getName);
        TreeSet<Student> set2 = new TreeSet<>(nameComparator);
        set2.add(new Student("张三", 20));
        set2.add(new Student("李四", 18));
        set2.add(new Student("王五", 22));
        System.out.println("按姓名排序: " + set2);
    }
}

输出

按年龄排序: [Student{name='李四', age=18}, Student{name='张三', age=20}, Student{name='王五', age=22}]
按姓名排序: [Student{name='张三', age=20}, Student{name='李四', age=18}, Student{name='王五', age=22}]

4. 使用场景

Comparable
  • 适用
    • 类有明确的自然排序(如 String 按字典序,Integer 按数值)。
    • 你控制类的代码,可以修改它。
  • 示例
    • TreeSet、TreeMap 默认使用元素的 compareTo。
    • 内置类如 String、Integer 已实现。
Comparator
  • 适用
    • 不想修改原始类(无源码或不便修改)。
    • 需要多种排序方式。
    • 临时排序需求。
  • 示例
    • Collections.sort(list, comparator)。
    • Arrays.sort(array, comparator)。
    • TreeSet 或 TreeMap 的构造方法传递比较器。

5. 实现细节

Comparable
  • 返回值
    • < 0:当前对象小于参数对象。
    • = 0:相等。
    • > 0:当前对象大于参数对象。
  • 要求
    • 自反性、对称性、传递性。
    • 与 equals 一致(建议但非强制)。
Comparator
  • 返回值:同上。
  • 便捷方法(Java 8+):
    • Comparator.comparing(keyExtractor):按指定字段排序。
    • thenComparing():多条件排序。
    • reversed():反转顺序。
示例(多条件排序)
Comparator<Student> comparator = Comparator
    .comparing(Student::getAge)         // 按年龄排序
    .thenComparing(Student::getName);   // 年龄相同按姓名排序

6. 优缺点

Comparable
  • 优点
    • 定义自然顺序,简单直接。
    • 默认支持排序集合。
  • 缺点
    • 侵入式,只能有一种排序方式。
    • 不灵活。
Comparator
  • 优点
    • 非侵入式,类无需改动。
    • 支持多种排序规则。
  • 缺点
    • 需要额外定义,代码稍复杂。
    • 不作为类的默认行为。

7. 总结

  • Comparable
    • 类内部实现,定义自然排序。
    • 适合固定排序规则。
  • Comparator
    • 外部定义,灵活指定排序。
    • 适合动态或多样的排序需求。
  • 选择依据
    • 如果类有唯一自然的顺序,用 Comparable。
    • 如果需要外部控制或多种排序,用 Comparator。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值