手册目录

Java 迭代器接口

Java 错误和异常类型

Java.io 包教程

Java 教程

浏览6134
更新时间2025-07-22

前言

Java 高级排序在“列表排序”章节中,您学习了如何按字母顺序和数字顺序对列表进行排序,但如果列表中包含对象呢?为了对对象进行排序,您需要指定一个规则来决定对象

Java 高级排序

在“列表排序”章节中,您学习了如何按字母顺序和数字顺序对列表进行排序,但如果列表中包含对象呢?

为了对对象进行排序,您需要指定一个规则来决定对象的排序方式。例如,如果您有一个汽车列表,你可能想按年份排序,规则可以是年份较早的汽车排在前面。

ComparatorComparable 接口允许你指定用于排序对象的规则。

能够指定排序规则还允许您改变字符串和数字的排序方式。

Comparator(比较器)

实现了 Comparator 接口的对象被称为比较器。

Comparator 接口允许你创建一个包含 compare() 方法的类,该方法比较两个对象以决定哪个在列表中应排在前面。

compare() 方法应返回一个数字,该数字:

  • 为负数时,表示第一个对象应在列表中排在前面。
  • 为正数时,表示第二个对象应在列表中排在前面。
  • 为零时,表示顺序无关紧要。

实现 Comparator 接口的类可能如下所示:

// 按年份排序 Car 对象
class SortByYear implements Comparator {
  public int compare(Object obj1, Object obj2) {
    // 确保对象是 Car 对象
    Car a = (Car) obj1;
    Car b = (Car) obj2;
    
    // 比较对象
    if (a.year < b.year) return -1; // 第一辆车的年份更小
    if (a.year > b.year) return 1;  // 第一辆车的年份更大
    return 0; // 两辆车的年份相同
  }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

要使用比较器,将其作为参数传递给排序方法:

// 使用比较器对汽车进行排序
Comparator myComparator = new SortByYear();
Collections.sort(myCars, myComparator);

运行实例 »

点击 "运行实例" 按钮查看在线实例

下面是一个使用比较器按年份排序汽车列表的完整示例:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

// 定义一个 Car 类
class Car {
  public String brand; // 品牌
  public String model; // 型号
  public int year; // 年份
  
  // 构造函数
  public Car(String b, String m, int y) {
    brand = b;
    model = m;
    year = y;
  }
}

// 创建一个比较器
class SortByYear implements Comparator {
  // 实现 compare 方法
  public int compare(Object obj1, Object obj2) {
    // 确保传入的对象是 Car 类型
    Car a = (Car) obj1;
    Car b = (Car) obj2;
    
    // 比较两辆车的年份
    if (a.year < b.year) return -1; // 第一辆车年份更小
    if (a.year > b.year) return 1;  // 第一辆车年份更大
    return 0; // 两辆车年份相同
  }
}

public class Main { 
  public static void main(String[] args) { 
    // 创建一个汽车列表
    ArrayList<Car> myCars = new ArrayList<Car>();    
    myCars.add(new Car("BMW", "X5", 1999));
    myCars.add(new Car("Honda", "Accord", 2006));
    myCars.add(new Car("Ford", "Mustang", 1970));

    // 使用比较器对汽车进行排序
    Comparator myComparator = new SortByYear();
    Collections.sort(myCars, myComparator);

    // 显示排序后的汽车
    for (Car c : myCars) {
      System.out.println(c.brand + " " + c.model + " " + c.year);
    }
  } 
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

使用 Lambda 表达式

为了简化代码,比较器可以被替换为具有与 compare() 方法相同参数和返回值的 Lambda 表达式:

Collections.sort(myCars, (obj1, obj2) -> {
  Car a = (Car) obj1;
  Car b = (Car) obj2;
  if (a.year < b.year) return -1;
  if (a.year > b.year) return 1;
  return 0;
});

运行实例 »

点击 "运行实例" 按钮查看在线实例

特殊排序规则

比较器还可以用于为字符串和数字制定特殊的排序规则。在此例中,我们使用比较器将所有偶数列在奇数之前:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

// 定义一个比较器类 SortEvenFirst,实现 Comparator 接口
class SortEvenFirst implements Comparator {
  // 实现 compare 方法,用于比较两个对象
  public int compare(Object obj1, Object obj2) {
    // 确保传入的对象是 Integer 类型
    Integer a = (Integer) obj1;
    Integer b = (Integer) obj2;
    
    // 检查每个数字是否为偶数
    // 一个数字如果除以 2 的余数为 0,则为偶数
    boolean aIsEven = (a % 2) == 0;
    boolean bIsEven = (b % 2) == 0;
    
    // 如果两个数字同为偶数或同为奇数,则按正常排序规则比较
    if (aIsEven == bIsEven) {
      if (a < b) return -1; // a小于b,返回-1
      if (a > b) return 1;  // a大于b,返回1
      return 0;             // a等于b,返回0
    } else {
      // 如果 a 是偶数,则 a 排在前面,否则 b 排在前面
      if (aIsEven) {
        return -1; // a 是偶数,返回 -1,表示 a 排在前面
      } else {
        return 1;  // b 是偶数,返回 1,表示 b 排在前面
      }
    }
  }
}

public class Main {
  public static void main(String[] args) {
    // 创建一个 Integer 类型的 ArrayList
    ArrayList<Integer> myNumbers = new ArrayList<Integer>();
    // 向列表中添加一些整数
    myNumbers.add(33);
    myNumbers.add(15);
    myNumbers.add(20);
    myNumbers.add(34);
    myNumbers.add(8);
    myNumbers.add(12);

    // 创建一个 SortEvenFirst 比较器实例
    Comparator myComparator = new SortEvenFirst();
    // 使用该比较器对列表进行排序
    Collections.sort(myNumbers, myComparator);

    // 遍历并打印排序后的列表
    for (int i : myNumbers) {
      System.out.println(i);
    }
  }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

Comparable 接口

Comparable 接口允许对象通过 compareTo() 方法指定其自身的排序规则。

compareTo() 方法接受一个对象作为参数,并将可比较对象与该参数进行比较,以决定哪个在列表中应排在前面。

与比较器类似,compareTo() 方法返回一个数字,该数字:

  • 为负数时,表示可比较对象应在列表中排在前面。
  • 为正数时,表示另一个对象应在列表中排在前面。
  • 为零时,表示顺序无关紧要。

许多原生 Java 类(如 StringInteger)都实现了 Comparable 接口。

这就是为什么字符串和数字不需要比较器就可以进行排序的原因。

实现了 Comparable 接口的对象可能如下所示:

class Car implements Comparable {
  public String brand; // 品牌
  public String model; // 型号
  public int year;     // 年份
  
  // 定义此对象如何与其他对象进行比较
  public int compareTo(Object obj) {
    Car other = (Car) obj; // 将传入的对象强制转换为Car类型
    if (year < other.year) return -1; // 如果此对象的年份小于另一个对象的年份,则返回 -1,表示此对象较小
    if (year > other.year) return 1;  // 如果此对象的年份大于另一个对象的年份,则返回 1,表示此对象较大
    return 0; // 如果两个对象的年份相同,则返回 0,表示两个对象相等(在年份上)
  }
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

下面是与之前相同的示例,但使用 Comparable 接口而不是比较器:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

// 定义一个可比较的 Car 类
class Car implements Comparable<Car> {
  public String brand; // 品牌
  public String model; // 型号
  public int year;     // 年份
  
  // 构造方法,用于初始化 Car 对象
  public Car(String b, String m, int y) {
    brand = b;
    model = m;
    year = y;
  }
  
  // 实现 compareTo 方法,决定此对象如何与其他 Car 对象进行比较
  @Override
  public int compareTo(Car other) {
    if (year < other.year) return -1; // 如果此车的年份小于另一辆车的年份,则返回 -1,表示此车较小
    if (year > other.year) return 1;  // 如果此车的年份大于另一辆车的年份,则返回 1,表示此车较大
    return 0; // 如果两车的年份相同,则返回 0,表示两车相等(在年份上)
  }
}

public class Main { 
  public static void main(String[] args) { 
    // 创建一个汽车列表
    ArrayList<Car> myCars = new ArrayList<Car>();    
    myCars.add(new Car("BMW", "X5", 1999));
    myCars.add(new Car("Honda", "Accord", 2006));
    myCars.add(new Car("Ford", "Mustang", 1970));

    // 对汽车进行排序
    Collections.sort(myCars);

    // 显示汽车列表
    for (Car c : myCars) {
      System.out.println(c.brand + " " + c.model + " " + c.year);
    }
  } 
}

运行实例 »

点击 "运行实例" 按钮查看在线实例

常见的排序技巧

最直观的按自然顺序排序两个数字的方法是编写如下代码:

if(a.year < b.year) return -1; // a 小于 b
if(a.year > b.year) return 1; // a 大于 b
return 0; // a is equal to b

运行实例 »

点击 "运行实例" 按钮查看在线实例

但实际上,这可以用一行代码完成:

return a.year - b.year;

运行实例 »

点击 "运行实例" 按钮查看在线实例

这个技巧还可以用于轻松实现反向排序:

return b.year - a.year;

运行实例 »

点击 "运行实例" 按钮查看在线实例

Comparator vs. Comparable

比较器(comparator)是一个具有一个方法的对象,用于比较两个不同的对象。

可比较对象(comparable)是一个可以与其他对象进行比较的对象。

在可能的情况下,使用 Comparable 接口更容易,但 Comparator 接口更强大,因为它允许你对任何类型的对象进行排序,即使你不能更改其代码。

相关视频

更多

免费

php8,我来也
初级php8,我来也

321756次学习

收藏

免费

Thinkphp6.0正式版视频教程
中级Thinkphp6.0正式版视频教程

382411次学习

收藏

免费

细说PHP第一季
中级细说PHP第一季

282705次学习

收藏

免费

简单聊聊PHP创业那点事
初级简单聊聊PHP创业那点事

13413次学习

收藏

精品课程

更多
前端入门_HTML5
前端入门_HTML5

共29课时 | 62.5万人学习

CSS视频教程-玉女心经版
CSS视频教程-玉女心经版

共25课时 | 39.7万人学习

JavaScript极速入门_玉女心经系列
JavaScript极速入门_玉女心经系列

共43课时 | 73.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号