手册
目录
收藏96
分享
阅读808
更新时间2025-07-22
前言:
Java 高级排序在“列表排序”章节中,您学习了如何按字母顺序和数字顺序对列表进行排序,但如果列表中包含对象呢?为了对对象进行排序,您需要指定一个规则来决定对象
在“列表排序”章节中,您学习了如何按字母顺序和数字顺序对列表进行排序,但如果列表中包含对象呢?
为了对对象进行排序,您需要指定一个规则来决定对象的排序方式。例如,如果您有一个汽车列表,你可能想按年份排序,规则可以是年份较早的汽车排在前面。
Comparator 和 Comparable 接口允许你指定用于排序对象的规则。
能够指定排序规则还允许您改变字符串和数字的排序方式。
实现了 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 myCars = new ArrayList();
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);
}
}
}
点击 "运行实例" 按钮查看在线实例
为了简化代码,比较器可以被替换为具有与 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 myNumbers = new ArrayList();
// 向列表中添加一些整数
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 接口允许对象通过 compareTo() 方法指定其自身的排序规则。
compareTo() 方法接受一个对象作为参数,并将可比较对象与该参数进行比较,以决定哪个在列表中应排在前面。
与比较器类似,compareTo() 方法返回一个数字,该数字:
许多原生 Java 类(如 String 和 Integer)都实现了 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{ 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 myCars = new ArrayList (); 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
点击 "运行实例" 按钮查看在线实例
但实际上,这可以用一行代码完成:
这个技巧还可以用于轻松实现反向排序:
比较器(comparator)是一个具有一个方法的对象,用于比较两个不同的对象。
可比较对象(comparable)是一个可以与其他对象进行比较的对象。
在可能的情况下,使用 Comparable 接口更容易,但 Comparator 接口更强大,因为它允许你对任何类型的对象进行排序,即使你不能更改其代码。
相关
视频
RELATED VIDEOS
科技资讯
1
2
3
4
5
6
7
8
9
精选课程
共5课时
17.2万人学习
共49课时
77万人学习
共29课时
61.7万人学习
共25课时
39.3万人学习
共43课时
70.9万人学习
共25课时
61.6万人学习
共22课时
23万人学习
共28课时
33.9万人学习
共89课时
125万人学习