Arrays与Collection中自定义Comparator接口配合lambda实现自定义sort

问题

 刷到一个算法题需要拼接数字组成一个最大数,基本思想是高位比较,相等比较下一位,然后根据大小先拼接大的,再拼接小的,但是发现当存在多个数字高位相同时面临一个问题,比如示例2中,3,30,34,肯定先拼接34,但是30和3应该拼接为330,先是3再拼30,而不是303,因此转换思路,只需要将两个数线拼接起来,比较一下拼接后的结果哪个大,就把哪个数放前面,就不用逐位比较了,实现很容易如下:

class Solution {
    public String largestNumber(int[] nums) {
        String[] strs = new String[nums.length];
        for(int i=0; i<nums.length; i++){
            strs[i] = String.valueOf(nums[i]);
        }
        Arrays.sort(strs, (a,b)->(b+a).compareTo(a+b));
        if(strs[0].equals("0")){
            return "0";
        }
        StringBuilder sb = new StringBuilder();
        for(String s : strs){
            sb.append(s);
        }
        return sb.toString();
    }
}

但重点不是这个,而是其中对Arrays的sort排序重写的comparator接口:

Arrays.sort(strs, (a,b)->(b+a).compareTo(a+b));

源码如下: 

    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接口

先以整数为例,最基础的方式如下:

 通过定义一个类实现Comparator接口,重写里面的compare方法,返回o1-o2,o1-o2为升序,o2-o1为降序

class B implements Comparator<Integer> {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1-o2;
    }
}
public class test {
    public static void main(String[] args) {
        Integer[] nums = {3,30,34,5,9};
        System.out.println("排序前"+Arrays.toString(nums));
        Arrays.sort(nums, new B());
        System.out.println("排序后"+Arrays.toString(nums));
    }
}

匿名内部类实现 

进一步来写,可以将外部定义的类改为匿名内部类,如下所示:

public class test {
    public static void main(String[] args) {
        Integer[] nums = {3,30,34,5,9};
        System.out.println("排序前"+Arrays.toString(nums));
        Arrays.sort(nums, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        System.out.println("排序后"+Arrays.toString(nums));
    }
}

 lambda表达式

再进一步,可以更精简,追求更极致的简洁采用lambda表达式去写

public class test {
    public static void main(String[] args) {
        Integer[] nums = {3,30,34,5,9};
        System.out.println("排序前"+Arrays.toString(nums));
        Arrays.sort(nums, (Integer o1, Integer o2) -> {return o1-o2;});
        System.out.println("排序后"+Arrays.toString(nums));
    }
}

在lambda中甚至变量类型和return都能省略,因此可以写成这样: 

Arrays.sort(nums, ( o1,  o2) -> o1 - o2 );

String的自定义比较方法

回到最开始的问题,因为要比较的是String对象而不是Integer对象,String不像Integer能够直接用减号“-”去比较大小,而且直接给出比较结果如-1只是将元素进行了逆序排列而已,并没有达到题目要求:

public class test {
    public static void main(String[] args) {
        Integer[] nums = {3,30,34,5,9};
        String[] strs = new String[nums.length];
        for(int i=0; i<nums.length; i++){
            strs[i] = String.valueOf(nums[i]);
        }
        System.out.println("排序前"+Arrays.toString(strs));
        Arrays.sort(strs, ( o1,  o2) -> -1 );
        System.out.println("排序后"+Arrays.toString(strs));
    }
}

 因此针对String类型的数据要采取另一种方式,恰好String类提供了compareTo方法,compareTo方法有两个特点:

  • 字符串与对象进行比较。
  • 按字典顺序比较两个字符串。

因此它可以很好的根据ASCLL码比较由数字拼接在一起的字符串的大小。

public class test {
    public static void main(String[] args) {
        Integer[] nums = {3,30,34,5,9};
        String[] strs = new String[nums.length];
        for(int i=0; i<nums.length; i++){
            strs[i] = String.valueOf(nums[i]);
        }
        System.out.println("排序前"+Arrays.toString(strs));
//        Arrays.sort(strs, ( o1,  o2) -> -1 );
        Arrays.sort(strs, (a, b)->(b+a).compareTo(a+b));
        System.out.println("排序后"+Arrays.toString(strs));
    }
}

 此时可以发现,排序后的String数组的元素按照拼接后能组成最大数的顺序进行了排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值