Java编程笔记——基于Comparator与sort的自定义排序

Arrays中有一个双参的的sort方法

    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接口中的compare抽象方法来完成自定义的排序,当然,第二个参数可以用匿名内部类的方式来实现,进一步可以用lambda表达式来实现

那么Comparator接口该如何重写呢?

必须要重写的是compare方法,我们看一下compare方法的描述

     * @return a negative integer, zero, or a positive integer as the
     *         first argument is less than, equal to, or greater than the
     *         second.
	int compare(T o1, T o2);
  • 如果返回的是负值,代表第一个参数小于第二个参数,零代表相等,正数代表第一个参数大于第二个参数,这里的大于也可以认为是放在后面,因为可以通过返回值取反的反射光hi实现降序排列,即升序一减二,降序而减一
  • 这里的泛型T可以由Comparator<T>来指定

下面给出具体的实例

在leetcode题库中的根据身高重建队列问题,就需要对二维数组people[][]进行排序,对于int person : people,如果person[0]大,则放在前面,如果person[0]相等,则person[1]小的放在前面,所以可以通过自定义排序方式来获得这种排序后的结果,给出代码实现如下:

public class Solution {
    public int[][] reconstructQueue(int[][] people) {

        //传递实现了接口的类
        MyComparator myComparator = new MyComparator();
        Arrays.sort(people, myComparator);

        //使用匿名内部类
        Arrays.sort(people, new Comparator<int[]>() {
            @Override
            public int compare(int[] person1, int[] person2) {
                if (person1[0] != person2[0]) {
                    return person2[0] - person1[0];
                } else {
                    return person1[1] - person2[1];
                }
            }
        });

        //使用lambda表达式
        Arrays.sort(people, (person1, person2) -> {
            if (person1[0] != person2[0]) {
                return person2[0] - person1[0];
            } else {
                return person1[1] - person2[1];
            }
        });

        //算法处理
        List<int[]> result = new ArrayList<>();

        for (int[] person : people) {
            result.add(person[1], person);
        }

        return result.toArray(new int[result.size()][]);
    }
}

class MyComparator implements Comparator<int[]> {
    @Override
    public int compare(int[] o1, int[] o2) {
        if (o1[0] != o2[0]) {
            return o2[0] - o1[0];
        } else {
            return o1[1] - o2[1];
        }
    }
}

但是这里有一个问题,直接使用onject1 - object2需要注意溢出的问题,比如o1 = -2^32, o2 = 2^32,当二者做减法时会出现溢出的问题,最终得出正的结果
在这里插入图片描述
原因在于,在运算过程中,-2147483646的二进制原码为
11111111111111111111111111111110
反码
1000000000000000000000000001
补码
1000000000000000000000000010
做减法
  1000000000000000000000000010
+1000000000000000000000000010
————————————————
10000000000000000000000000100

最后一位由于溢出会被丢弃,因此得到的是0000000000000000000000000100,对其取原码仍为0000000000000000000000000100,也就是4.
因此用以下的写法更加安全

        Arrays.sort(points, (points1, points2) -> {
            return points1[1] < points2[1] ? -1 : 1;
        });
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值