版权声明:本文为博主原创文章,转载请注明出处: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;
    }
}

代码中我们使用了数组的排序方法 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
        (实际参数列表和形式参数列表长度不同))

原因是 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));

林皓伟

发表回复

您的电子邮箱地址不会被公开。