Arrays中有一个双参的的sort方法
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
这一方法第一个参数为待排序的对象,第二的参数为实现了Comparator接口的类,通过实现Comparator接口中的compare抽象方法来完成自定义的排序,当然,第二个参数可以用匿名内部类的方式来实现,进一步可以用lambda表达式来实现
那么Comparator接口该如何重写呢?
必须要重写的是compare方法,我们看一下compare方法的描述
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
int compare(T o1, T o2);
- 如果返回的是负值,代表第一个参数小于第二个参数,零代表相等,正数代表第一个参数大于第二个参数,这里的大于也可以认为是放在后面,因为可以通过返回值取反的反射光hi实现降序排列,即升序一减二,降序而减一
- 这里的泛型T可以由Comparator<T>来指定
下面给出具体的实例
在leetcode题库中的根据身高重建队列问题,就需要对二维数组people[][]进行排序,对于int person : people,如果person[0]大,则放在前面,如果person[0]相等,则person[1]小的放在前面,所以可以通过自定义排序方式来获得这种排序后的结果,给出代码实现如下:
public class Solution {
public int[][] reconstructQueue(int[][] people) {
//传递实现了接口的类
MyComparator myComparator = new MyComparator();
Arrays.sort(people, myComparator);
//使用匿名内部类
Arrays.sort(people, new Comparator<int[]>() {
@Override
public int compare(int[] person1, int[] person2) {
if (person1[0] != person2[0]) {
return person2[0] - person1[0];
} else {
return person1[1] - person2[1];
}
}
});
//使用lambda表达式
Arrays.sort(people, (person1, person2) -> {
if (person1[0] != person2[0]) {
return person2[0] - person1[0];
} else {
return person1[1] - person2[1];
}
});
//算法处理
List<int[]> result = new ArrayList<>();
for (int[] person : people) {
result.add(person[1], person);
}
return result.toArray(new int[result.size()][]);
}
}
class MyComparator implements Comparator<int[]> {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] != o2[0]) {
return o2[0] - o1[0];
} else {
return o1[1] - o2[1];
}
}
}
但是这里有一个问题,直接使用onject1 - object2需要注意溢出的问题,比如o1 = -2^32, o2 = 2^32,当二者做减法时会出现溢出的问题,最终得出正的结果
原因在于,在运算过程中,-2147483646的二进制原码为
11111111111111111111111111111110
反码
1000000000000000000000000001
补码
1000000000000000000000000010
做减法
1000000000000000000000000010
+1000000000000000000000000010
————————————————
10000000000000000000000000100
最后一位由于溢出会被丢弃,因此得到的是0000000000000000000000000100,对其取原码仍为0000000000000000000000000100,也就是4.
因此用以下的写法更加安全
Arrays.sort(points, (points1, points2) -> {
return points1[1] < points2[1] ? -1 : 1;
});