【Java】重写比较器java.util.Comparator的注意事项

版权声明:本文为博主原创文章,转载请注明出处:https://twocups.cn/index.php/2020/02/05/18/

有时我们需要对同一类型的对象进行多种不同方式的排序,而自然排序 Comparable 并不能实现。这里我们就需要重写比较器,可以让对象数组或集合以自定义的排序规则进行排序。

示例

给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。例如 [10, 2] 的输出为210,[3, 30, 34, 5, 9] 的输出为9534330。

这道题解法的关键就是排序,具体的规则为:数组中的非负整数(例如 xy)两两进行比较,若x + y > y + x,则判定 x 的优先级比 y 高,且 x 在最终的整数里排在 y 的前面。

代码

import java. util . Arrays ;
import java. util . Comparator ;
class Test {
public String largestNumber ( int [] nums ) {
Integer [] arr = new Integer [ nums. length ] ;
for ( int i = 0 ; i < nums. length ; i++ ) arr [ i ] = nums [ i ] ;
Arrays. sort ( arr, new Comparator < Integer >(){
@Override
public int compare ( Integer o1, Integer o2 ){
String s1 = o1 + "" + o2;
String s2 = o2 + "" + o1;
return s2. compareTo ( s1 ) ;
}
}) ;
StringBuffer sb = new StringBuffer () ;
for ( int x: arr ) sb. append ( x ) ;
String res = sb. toString () ;
return res. charAt ( 0 ) == '0' ? "0" : res;
}
}
import java.util.Arrays; import java.util.Comparator;

class Test{
public String largestNumber(int[] nums) {
Integer[] arr = new Integer[nums.length];
for(int i = 0; i < nums.length; i++) arr[i] = nums[i];
Arrays.sort(arr, new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2){
String s1 = o1 + “” + o2;
String s2 = o2 + “” + o1;
return s2.compareTo(s1);
}
});
StringBuffer sb = new StringBuffer();
for(int x: arr) sb.append(x);
String res = sb.toString();
return res.charAt(0) == ‘0’ ? “0” : res;
}
}

import java.util.Arrays;
import java.util.Comparator;

class Test{
public String largestNumber(int[] nums) {
Integer[] arr = new Integer[nums.length];
for(int i = 0; i < nums.length; i++) arr[i] = nums[i];
Arrays.sort(arr, new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2){
String s1 = o1 + “” + o2;
String s2 = o2 + “” + o1;
return s2.compareTo(s1);
}
});
StringBuffer sb = new StringBuffer();
for(int x: arr) sb.append(x);
String res = sb.toString();
return res.charAt(0) == ‘0’ ? “0” : res;
}
}

代码中我们使用了数组的排序方法 sort(),并且重写了一个比较器 Comparator 来定义数组中元素在排序时两两之间的比较规则。如果是集合,同样也可以使用 Collections 的排序方法 sort()。有些人在使用这个方法的时候会遇到如下问题:

英文版:
Error: java: no suitable method found for sort ( char [] , < anonymous java. util . Comparator < java. lang . Character >>)
method java. util . Arrays . < T > sort ( T [] ,java. util . Comparator < ? super T >) is not applicable
( inference variable T has incompatible bounds
equality constraints: char
upper bounds: java. lang . Character ,java. lang . Object )
method java. util . Arrays . < T > sort ( T [] ,int,int,java. util . Comparator < ? super T >) is not applicable
( cannot infer type- variable ( s ) T
( actual and formal argument lists differ in length ))
中文版:
Error: java: 对于 sort ( char [] , < 匿名java. util . Comparator < java. lang . Character >>) , 找不到合适的方法
方法 java. util . Arrays . < T > sort ( T [] ,java. util . Comparator < ? super T >) 不适用
( 推论变量 T 具有不兼容的限制范围
等式约束条件: char
上限: java. lang . Character ,java. lang . Object )
方法 java. util . Arrays . < T > sort ( T [] ,int,int,java. util . Comparator < ? super T >) 不适用
( 无法推断类型变量 T
( 实际参数列表和形式参数列表长度不同 ))
英文版: Error: java: no suitable method found for sort(char[],<anonymous java.util.Comparator<java.lang.Character>>) method java.util.Arrays.<T>sort(T[],java.util.Comparator<? super T>) is not applicable (inference variable T has incompatible bounds equality constraints: char upper bounds: java.lang.Character,java.lang.Object) method java.util.Arrays.<T>sort(T[],int,int,java.util.Comparator<? super T>) is not applicable (cannot infer type-variable(s) T (actual and formal argument lists differ in length)) 中文版: Error: java: 对于sort(char[],<匿名java.util.Comparator<java.lang.Character>>), 找不到合适的方法 方法 java.util.Arrays.<T>sort(T[],java.util.Comparator<? super T>)不适用 (推论变量 T 具有不兼容的限制范围 等式约束条件: char 上限: java.lang.Character,java.lang.Object) 方法 java.util.Arrays.<T>sort(T[],int,int,java.util.Comparator<? super T>)不适用 (无法推断类型变量 T (实际参数列表和形式参数列表长度不同))
英文版:
Error: java: no suitable method found for sort(char[],<anonymous java.util.Comparator<java.lang.Character>>)
    method java.util.Arrays.<T>sort(T[],java.util.Comparator<? super T>) is not applicable
      (inference variable T has incompatible bounds
        equality constraints: char
        upper bounds: java.lang.Character,java.lang.Object)
    method java.util.Arrays.<T>sort(T[],int,int,java.util.Comparator<? super T>) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ in length))
中文版:
Error: java: 对于sort(char[],<匿名java.util.Comparator<java.lang.Character>>), 找不到合适的方法
    方法 java.util.Arrays.<T>sort(T[],java.util.Comparator<? super T>)不适用
      (推论变量 T 具有不兼容的限制范围
        等式约束条件: char
        上限: java.lang.Character,java.lang.Object)
    方法 java.util.Arrays.<T>sort(T[],int,int,java.util.Comparator<? super T>)不适用
      (无法推断类型变量 T
        (实际参数列表和形式参数列表长度不同))

原因是 public static void sort (T [] a,Comparator c) 是根据指定比较器引发的顺序对指定的对象数组进行排序,所以 sort() 方法的第一个参数 T [] a 中只能存放对象,而不能存放基本数据类的数据。如果将 char 类型的数组传入该方法,则会报出以上错误;如果传入的是 Character 类型的数组,则正常。

这里可能有人要问了,char 类型的数据和 Character 类型的数据不是会自动装箱和封箱吗,那为什么这里两者的数组不能通用呢?

通用不代表混用。char 在 Java 中属于八大基本数据类型,不需要实例化就能直接使用;而 Character 是 char 的封装类,需要实例化后才能用。一般来说,char 类型的数据和 Character 类型的数据会动态地进行自动封箱和装箱,来满足不同的需求,但是 char 类型的数组和 Character 类型的数组并不会自动转换啊,它们的本质是数组,只是存放了两种类型的数据而已。

所以如果之前得到的是 char 类型的数组,需要我们自己新建其封装类数组,并将 char 数组的元素全部装入其封装类数组中(这里将元素装入时才会自动封箱)。

其实,在特殊情况下还有更加方便的写法,我举两个例子。

// 将排序的参照要素从数组中的元素变成该元素的某个部分
int [] nums = new int []{{ 2 , 5 } , { 3 , 7 } , { 1 , 5 } , { 9 , 1 }} ;
Arrays. sort ( nums , Comparator. comparingInt ( a - > a [ 0 ])) ;
// 改变排序所依照的两个元素的比较方式
String [] strs = new String []{ "aaa" , "bbb" } ;
Arrays. sort ( strs , ( x, y ) - > y. compareTo ( x )) ;
// 优先队列:由原来的升序排序,到现在的根据元素的time属性降序排序
PriorityQueue < Integer > priorityQueue = new PriorityQueue <>(( a, b ) - > ( b. time - a. time )) ;
// 将排序的参照要素从数组中的元素变成该元素的某个部分 int[] nums = new int[]{{2, 5}, {3, 7}, {1, 5}, {9, 1}}; Arrays.sort(nums , Comparator.comparingInt(a -> a[0])); // 改变排序所依照的两个元素的比较方式 String[] strs = new String[]{"aaa", "bbb"}; Arrays.sort(strs , (x, y) -> y.compareTo(x));

// 优先队列:由原来的升序排序,到现在的根据元素的time属性降序排序
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((a, b) -> (b.time - a.time));

// 将排序的参照要素从数组中的元素变成该元素的某个部分
int[] nums = new int[]{{2, 5}, {3, 7}, {1, 5}, {9, 1}};
Arrays.sort(nums , Comparator.comparingInt(a -> a[0]));
// 改变排序所依照的两个元素的比较方式
String[] strs = new String[]{“aaa”, “bbb”};
Arrays.sort(strs , (x, y) -> y.compareTo(x));

// 优先队列:由原来的升序排序,到现在的根据元素的time属性降序排序
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((a, b) -> (b.time - a.time));

相关文章

【Java】Java语言的反射机制

【Java】Static执行顺序详解(什么情况下父类普通代码块会先运行?)

【Java】String与各种数据类型之间的转换

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值