Comparator接口排序原理
在使用Arrays.sort()
和Collections.sort()
等sort()
方法进行排序时,我们经常会使用自定义的Comparator
接口进行自定义排序,来控制元素的顺序。
那么
Comparator
接口中的compare()
方法是如何控制元素顺序的呢?
compare()
函数的签名如下:
int compare(T o1, T o2)
我们拿Integer
类型举例,假设compare
方法实现如下:
int compare(Integer o1, Integer o2){
if(o1 > o2){
return 1;
}
return -1;
}
此时Arrays.sort()
的结果为升序排列,对于Comparator的使用,可以看我另一篇文章–Comparator接口排序讲解。
此时的
1
和-1
到底是如何控制排序的呢?
我们查看sort方法的相关源码,发现了排序中有这样一段代码:
该方法是在数组较小时的一个插入排序,该插入排序时,会判断compare
方法的返回值,如果返回值大于0,就交换两个元素,否则就不交换。
可以看到源码中的compare
方法的第一个参数是数组前面的一个元素,第二个参数是其该参数后面的参数,也就是第一个参数在数组位置的前面,第二个参数在第一个参数的后面。当compare
方法返回正数的时候,这两个元素就会进行交换,因此实现了排序算法。
对于上述的例子,我们的compare
方法的实现是当o1 > o2
时,返回正数,否则返回负数,也就是说,当o1 > o2
时,这两个元素要进行交换,我们都知道o1
总是在o2
前面的,所以该方法就是把大的元素尽量放在后面,从而完成了升序排序。那么如果实现降序排序,使用同样的思路,只需要让o1 < o2
时,返回正数即可。
这其实就是Comparator控制排序的原理。可以简单的理解为,正数负数控制着两个元素是否进交换,如果是正数,就交换两个元素,如果是负数或者零,就不进行交换,同时o1
和o2
代表了其在数组中的相对顺序,o1
在前,o2
在后。
经常使用的一种排序方式
有时候我们只是进行简单的升序降序排列,没有复杂的排序逻辑,经常把上述写法简写,如下所示
// 升序
int compare(Integer o1, Integer o2){
return o1 - o2;
}
// 降序
int compare(Integer o1, Integer o2){
return o2 - o1;
}
上述写法是常用的写法,为什么可以这么写?
首先,对于升序来说,o1 - o2有两种情况
- o1 > o2,其返回值是正数,那么会交换两者的位置,也就是大数o1会移动到后面,进而完成升序。
- o1 < o2,其返回值是负数,那么不会交换两者的位置,因为o1在o2前面,所以结果还是升序。
对于降序来说,o2 - o1 也有两种情况
- o2 > o1,其返回值是正数,那么会交换两者的位置,小数o1会移动到o2后面,进而完成降序。
- o2 < o1,其返回值是负数,那么不会交换两者的位置,因为o1在o2前面,所以结果还是降序。
总结: 对于compare的使用,只要明确o1位置在o2前面,正数交换位置,负数和零不交换就可以。
我的个人博客,欢迎访问!
无限进步的个人博客