手册目录
Java 教程
Java 方法
Java 类
Java 文件处理
Java 数据结构
Java 案例
Java 参考手册
Java 关键字
Java String 方法
Java Math 方法
Java Output 方法
Java Arrays 类
Java ArrayList 方法
Java LinkedList 方法
Java HashMap 方法
Java Scanner 方法
Java 迭代器接口
Java 错误和异常类型
Java.io 包教程
Java.lang 包教程
Java.math 包教程
java.time 包教程
Java.util 包教程
Java 正则表达式教程
java.util.zip 包教程
前言
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<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);
}
}
}
点击 "运行实例" 按钮查看在线实例
为了简化代码,比较器可以被替换为具有与 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 接口允许对象通过 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<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
点击 "运行实例" 按钮查看在线实例
但实际上,这可以用一行代码完成:
这个技巧还可以用于轻松实现反向排序:
比较器(comparator)是一个具有一个方法的对象,用于比较两个不同的对象。
可比较对象(comparable)是一个可以与其他对象进行比较的对象。
在可能的情况下,使用 Comparable 接口更容易,但 Comparator 接口更强大,因为它允许你对任何类型的对象进行排序,即使你不能更改其代码。
相关视频
科技资讯
24小时阅读榜
1
2
3
4
5
6
7
8
9
10
精品课程
共5课时 | 17.4万人学习
共49课时 | 78.1万人学习
共29课时 | 62.5万人学习
共25课时 | 39.7万人学习
共43课时 | 73.8万人学习