Comparator :是一个接口,有compare(a,b)方法,主要用来排序。
compare(a,b) 方法:根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。
compareTo:String 是字符串,它的比较用compareTo方法,它从第一位开始比较, 如果遇到不同的字符,则马上返回这两个字符的ascii值差值.返回值是int类型。
obj1.compareTo(obj2)如果该方法返回0,则表示两个对象相等,如果该方法返回一个正整数,则表明obj1大于obj2;如果该方法返回一个负整数,则表明obj1小于obj2。
当compare(a,b)方法返回值大于0(为true)时,交换o1和o2
以上结论参考:
Java中comparator接口与compare方法的实现
compareTo()方法
为什么写成compare(a,b){return a - b;}
表示从小到大排序了?
镜像问题:compare(a,b){return b - a;}
表示从大到小排序
public int compare(a,b){
return a - b;
}
/*
情况一:a > b
因为a > b所以a - b大于0,交换a,b,大的数排在了后面,因此是从小到大排序。
情况二:a < b
因为a < b所以a - b小于0,a,b不交换,小的数在前面,大的数在后面,因此还是从小到大排序。
*/
比较器的匿名内部类写法
以NC153 信封嵌套问题为例
比较大小最好不要使用减法,当遇到[[-2147483646,-2147483645],[2147483646,2147483647]] 就过不了了,这是因为差值过大而产生溢出。sort的时候不要用a-b来比较,用小于号比较做三目运算可以避免溢出。
把Comparator的泛型写做数组元素的类型,这样可以把二维数组看作元素是数组的一维数组,于时就可以给二维数组排序了。
Arrays.sort(letters,new Comparator<int[]>(){
public int compare(int[] a, int[] b){
if(a[0] == b[0]){
return b[1] < a[1] ? -1 : 1;
}
return a[0] < b[0] ? -1 : 1;
}
});
注意compare方法的参数类型要和匿名内部类的泛型一致,否则编译不通过,比如下面这个写法是不通过的。
//LeetCode451. 根据字符出现频率排序
Collections.sort(list,new Comparator<Character>(){
public int compare(char a, char b){
if(map.get(a) != map.get(b)){
return map.get(b) - map.get(a);
}
return a - b;
}
});
加入给map的entry排序可以这样写:
PriorityQueue<Map.Entry<Integer, Integer>> priorityQueue = new PriorityQueue<>(
new Comparator<Map.Entry<Integer, Integer>>() {
public int compare(Map.Entry<Integer, Integer> e1, Map.Entry<Integer, Integer> e2) {
return e1.getValue() - e2.getValue();
}
});
PriorityQueue<Map.Entry<Integer, Integer>> priorityQueue = new PriorityQueue<>(
(e1, e2) -> e1.getValue() - e2.getValue());
比较器的lambda写法
以NC85 拼接所有的字符串产生字典序最小的字符串中的小顶堆创建为例。
PriorityQueue<String> minHeap = new PriorityQueue<>((a,b)->{
return (a+b).compareTo(b+a);
});