Java 中的排序Comparable 与 Comparator 的使用与区别对比解析

 更新时间:2025年09月15日 11:46:47   作者:你我约定有三  
本文给大家介绍Java中的排序Comparable与Comparator的使用与区别对比,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

1. 背景

在 Java 中,如果我们希望自定义类能够进行排序(例如在集合、数组中排序),就需要定义对象的比较规则。

Java 提供了两种方式:

  • Comparable<T> 接口 → 在类内部实现,定义对象的“自然顺序”。
  • Comparator<T> 接口 → 在类外部定义比较器,可以灵活指定不同的排序规则。

2.Comparable接口

Java 中很多常用类都实现了 Comparable 接口,例如 StringInteger

public class CompareToDemo {
    public static void main(String[] args) {
        // String 按字典序比较
        System.out.println("apple".compareTo("banana")); // -1
        System.out.println("dog".compareTo("dog"));      // 0
        System.out.println("zoo".compareTo("apple"));    // 正数
        // Integer 按数值大小比较
        Integer a = 10, b = 20;
        System.out.println(a.compareTo(b)); // -1
        System.out.println(b.compareTo(a)); // 1
        System.out.println(a.compareTo(10));// 0
    }
}

2.1 定义

public interface Comparable<T> {
    int compareTo(T o);
}

2.2 返回值含义

  • 负数:当前对象 < 参数对象
  • 0:当前对象 == 参数对象
  • 正数:当前对象 > 参数对象

2.3 使用场景

当一个类本身就有固定的“自然排序规则”,可以直接实现 Comparable

3.Comparator接口

3.1 定义

public interface Comparator<T> {
    int compare(T o1, T o2);
}

3.2 返回值含义

Comparable 相同:

  • 负数 → o1 < o2
  • 0 → o1 == o2
  • 正数 → o1 > o2

3.3 使用场景

当我们不想修改类本身,或者需要定义多种排序规则时,使用 Comparator 更灵活。

4.ComparablevsComparator区别表

特性ComparableComparator
方法int compareTo(T o)int compare(T o1, T o2)
定义位置内部(实现接口)外部(单独写比较器)
排序规则数量一种(自然顺序)多种(可定义多个 Comparator)
修改类代码需求需要修改类本身不需要修改类本身
常见使用场景Collections.sort(list)Collections.sort(list, comparator)

5. Comparable 与 Comparator的使用示例:对List<Student>按age排序

5.1 使用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 name + "(" + age + ")";
    }
}
public class ComparableDemo {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("Alice", 22));
        list.add(new Student("Bob", 18));
        list.add(new Student("Charlie", 20));
        // 使用 Comparable 定义的 compareTo 方法排序
        Collections.sort(list);
        System.out.println(list); 
        // 输出: [Bob(18), Charlie(20), Alice(22)]
    }
}

5.2 使用Comparator

如果我们不想修改 Student 类,或者想要不同的排序规则,可以使用 Comparator

方式一:匿名内部类

Collections.sort(list, new Comparator<Student>() {
    @Override
    public int compare(Student s1, Student s2) {
        return Integer.compare(s1.getAge(), s2.getAge());
    }
});

方式二:Lambda 表达式(Java 8+推荐)

list.sort((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()));

方式三:方法引用(更简洁)

list.sort(Comparator.comparing(Student::getAge));

👉 输出结果同样是:

[Bob(18), Charlie(20), Alice(22)]

6. 多条件排序(进阶)

6.1使用Comparator实现多条件排序

使Comparator 时,可以轻松实现多条件排序。

例如:先按年龄升序,再按名字字母序升序

//方式一、方法引用 + 链式 Comparator
list.sort(
    Comparator.comparing(Student::getAge)
              .thenComparing(Student::getName)
);
//方式二、匿名内部类写法
list.sort(new Comparator<Student>() {
    @Override
    public int compare(Student s1, Student s2) {
        // 先按年龄排序
        int result = Integer.compare(s1.getAge(), s2.getAge());
        // 如果年龄相同,则按姓名排序
        if (result == 0) {
            result = s1.getName().compareTo(s2.getName());
        }
        return result;
    }
});
//方式三、Lambda 表达式写法(Java 8+ 推荐)
list.sort((s1, s2) -> {
    int result = Integer.compare(s1.getAge(), s2.getAge());
    if (result == 0) {
        result = s1.getName().compareTo(s2.getName());
    }
    return result;
});

6.2 那是不是不能使用Comparable完成多条件呢?

1️⃣Comparable的特点

  • Comparable自然排序(对象自己规定的排序规则)。
  • 一个类 只能实现一次 compareTo 方法,也就是说只能有一种排序逻辑。
  • 例子:
public class Student implements Comparable<Student> {
    private int age;
    private String name;
    @Override
    public int compareTo(Student other) {
        // 先按年龄,再按姓名
        int result = Integer.compare(this.age, other.age);
        if (result == 0) {
            result = this.name.compareTo(other.name);
        }
        return result;
    }
}

👉 这样就能实现 多条件排序,但限制是 Student 这个类就被固定死了,始终用这一套排序规则(先按年龄升序,再按名字字母序升序),如果后续想先按照名字字母就要改这个compareTo方法

2️⃣Comparator的特点

  • Comparator外部比较器,不修改实体类本身。
  • 可以定义多个不同的排序规则,根据需要随时切换。
  • 例子(用的上面使用Comparator 实现多条件排序的方式一):
Comparator<Student> byAgeThenName = 
    Comparator.comparing(Student::getAge)
              .thenComparing(Student::getName);
Comparator<Student> byNameThenAge = 
    Comparator.comparing(Student::getName)
              .thenComparing(Student::getAge);

👉 这样一个类(Student)就可以有 多种排序方式,灵活性更高。

3️⃣ 多条件的对比

  • Comparable:类内部定义,固定一种排序逻辑(可以写多条件,但只能有这一种)。
  • Comparator:类外部定义,可以有多种排序逻辑,灵活组合,推荐用于多条件排序。

👉 这样就能实现 多条件排序,但限制是 Student 这个类就被固定死了,始终用这一套排序规则

✅ 多条件排序,Comparable 也能实现(在 compareTo 里写多条件逻辑)。
❌ 但是 Comparable 只能有这一种排序方式,灵活性差。
👉 真正业务里,一般 多条件排序都会用 Comparator

7. 总结

  • Comparable:让类具备自然排序能力,适合“唯一固定规则”的场景。
  • Comparator:外部比较器,适合需要定义多种排序规则的场景。
    • 对于 List<Student>
    • 如果 Student 类实现了 Comparable,直接用 Collections.sort(list)
    • 如果不想改 Student 类,可以用 Comparator 方式排序。
  • 推荐使用 Comparator.comparing(...) + Lambda/方法引用,更简洁灵活。

到此这篇关于java--Java 中的排序:Comparable 与 Comparator 的使用与区别的文章就介绍到这了,更多相关java Comparable 与 Comparator使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Java中的Lambda表达式

    详解Java中的Lambda表达式

    这篇文章主要介绍了Java中的Lambda表达式的的相关资料,文中讲解非常详细,示例代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • Java API学习教程之正则表达式详解

    Java API学习教程之正则表达式详解

    正则表达式的强大众所周知,它令程序员的头痛程度也数一数二的。下面这篇文章主要给大家介绍了关于Java API学习教程之正则表达式的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • Java全局异常处理器实现过程解析

    Java全局异常处理器实现过程解析

    这篇文章主要介绍了Java全局异常处理器实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Spring中网络请求客户端WebClient的使用详解

    Spring中网络请求客户端WebClient的使用详解

    作为替代,Spring 官方已在 Spring 5 中引入了 WebClient 作为非阻塞式 Reactive HTTP 客户端,本文将通过样例演示如何使用 WebClient,希望对大家有所帮助
    2024-04-04
  • Java基于HttpClient实现RPC的示例

    Java基于HttpClient实现RPC的示例

    HttpClient可以实现使用Java代码完成标准HTTP请求及响应。本文主要介绍了Java基于HttpClient实现RPC,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 使用Spring boot标记一个方法过时

    使用Spring boot标记一个方法过时

    这篇文章主要介绍了使用Spring boot标记一个方法过时,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 解析Oracle数据库中的对象集合schema

    解析Oracle数据库中的对象集合schema

    这篇文章主要介绍了Oracle数据库中的对象集合schema,是Oracle数据库入门学习中的基础知识,需要的朋友可以参考下
    2015-11-11
  • IDEA Error:java:无效的源发行版:13的解决过程

    IDEA Error:java:无效的源发行版:13的解决过程

    之前用idea运行时,也会出现这种情况,后面通过网上的资料解决了这个问题,下面这篇文章主要给大家介绍了关于IDEA Error:java:无效的源发行版:13的解决过程,需要的朋友可以参考下
    2023-01-01
  • Java线程让步_动力节点Java学院整理

    Java线程让步_动力节点Java学院整理

    yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权。下面通过本文给大家介绍Java线程让步的相关知识,需要的朋友参考下吧
    2017-05-05
  • VSCode 配置 Spring Boot 项目开发环境的全过程

    VSCode 配置 Spring Boot 项目开发环境的全过程

    两三年前曾经试过配置Java环境, 存在不少问题作罢. 最近搜了下相关的文章, 感觉VSCode对Java项目的支持比三年前完善了不少. 今天实际配置了一下环境, 把自己常用的功能过了一遍, 基本能跑通开发流程, 做个笔记,需要的朋友可以参考下
    2024-03-03

最新评论