前言: 本文主要针对的是 Java 自带的排序函数/接口
0. 整体框架
1. Java 中数组的自定义排序方法
实现 Comparable 接口中的 compareTo 函数或实现 Comparator 接口中的 compare 函数
两者存在使用上的区别,大体而言,Comparable 接口是为类服务,Comparator 接口是为 sort (Arrays.sort / Collections.sort)方法服务
1.1 基本类型
基本类型存在很多种,这里举例 int 型数组
1.1.1 升序排列
例如想要升序排序 int 型数组 nums,可以通过调用 Arrays.sort(nums) 方法进行升序排列
int[] nums = new int[]{4, 1, 6, 3};
// 升序
Arrays.sort(nums);
具体来讲,Arrays 类中的 sort 方法这样写道
Sorts the specified array of objects into ascending order, according to the natural ordering of its elements.
解释: 根据指定数组元素的自然顺序将指定数组的对象(数组中的元素)递增排序
那么对于整数而言,就是按照升序排列
1.1.2 降序排列
那么如果我想降序排列呢?那么这种额外的“需求”就需要自定义一个比较器(Comparator),在定义完比较器后,可以由 Arrays.sort 重载函数实现这种额外的“需求”,下面是 Arrays.sort 重载函数
public static <T> void sort(T[] a, Comparator<? super T> c) {
// ....
}
下面这段话是关于这个函数的解释
Sorts the specified array of objects according to the order induced by the specified comparator
解释: 排序的顺序是通过指定的比较器(comparator)来推断出来的,以此将数组的对象(数组中的元素)进行排序
也就是说,这个函数要求我们自定义一个比较器(Comparator),通过引入 Comparator 接口,实现这个接口中的 compare 方法来告诉 Arrays.sort 函数如何排序
除此之外,我还应注意到,这个函数使用了泛型 T,因为泛型要求包容的必须是对象类型,而 int 是基本类型,所以第一个参数 T[] a 中的 a 不能是基本类型 int[]
好在 Java 中存在基本类型的包装类,例如: int 基本类型对应着 Integer 包装类,那么我们就通过如下方式,实现 int 型数组的降序排列
int[] nums = new int[]{4, 1, 6, 3};
// 降序
Integer[] newNums = new Integer[nums.length];
for (int i = 0; i < nums.length; i++) newNums[i] = nums[i];
Arrays.sort(newNums, new Comparator<>(){
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2) return -1;// 若此处指定为1, 则为升序
else if (o1 < o2) return 1;// 若此处指定为-1, 则为升序
else return 0;
}
});
关于为什么 compare 中 o1 > o2 时要返回 -1 是降序,我查询了诸多资料都得不到一个确切的解释。但是可以明确的是: 排序的顺序是基于返回值的
在升序情况下,对于 compare(Integer o1, Integer o2) 函数
if (o1 > o2) return 1; // 或其他正整数
else if (o1 < o2) return -1; // 或其他负整数
else return 0; // 两者相等时
在降序情况下,对于 compare(Integer o1, Integer o2) 函数
if (o1 > o2) return -1; // 或其他负整数
else if (o1 < o2) return 1; // 或其他负整数
else return 0; // 两者相等时
对于 compareTo(Integer o2) 函数也有
o1.compareTo(o2); // 升序
-o1.compareTo(o2); // 降序
由于 Java 8 引入的 Lambda 表达式,Arrays.sort 可以简化为
Arrays.sort(newNums, (Integer o1, Integer o2) -> {
if (o1 > o2) return -1;
else if (o1 < o2) return 1;
else return 0;
});
// 我们还可以省略掉参数的类型
Arrays.sort(newNums, (o1, o2) -> {
if (o1 > o2) return -1;
else if (o1 < o2) return 1;
else return 0;
});
// 当然,我们还可以直接调用 Integer 包装类中实现的 compareTo 方法(默认是升序)
// 所需要在 o1.compareTo(o2) 前加负号
Arrays.sort(newNums, (o1, o2) -> -o1.compareTo(o2));
// 此外,我们还可以调用 Collections 类中的 reverseOrder 方法来实现逆序
Arrays.sort(newNums, Collections.reverseOrder());
至此,我们可以完成基本类型的降序排序
1.2 对象(自定义)类型
对象类型存在很多种,这里举例 String 型数组
1.2.1 实现 Comparable 接口中的 compareTo 函数
// Comparable 接口一般由自定类所实现,例如有 Person 类,想以 age 升序排序 Person 对象
Class Person implements Comparable{
int age;
// ... 省略中间细节
// 实现了 Comparable 接口中的 compareTo 方法
@Override
public int compareTo(Object o) {
Person person = (Person)o;
if (this.age > person.age) return 1;
else if (this.age < person.age) return -1;
else return 0;
}
}
之后,便可以通过 Arrays.sort 以 age 升序排序 Person 对象
// 创建 Person 数组
Person[] persons = new Person[]{new Person(18), new Person(20)};
// 按照 age 升序排序 Person 对象
Arrays.sort(persons);
1.2.2 实现 Comparator 接口中的 compare 函数
同基本类型降序排序部分大同小异,在此不作叙述