Java进阶篇(1)— lambda与Comparator<T>排序接口(实现多条件排序)

Comparator代表一个比较器,比较的是两个对象。

/**
* @param o1 要比较的第一个对象;
* @param o2 要比价的第二个对象;
* @reture 若o1小于02,返回负整数;o1等于o2返回0;o1大于o2返回正整数;
**/
int compare(T o1,T o2)

Comparator [肯派瑞特] 比较器
comparable[抗母普瑞堡] 可比较的

1. comparable和comparator的区别

comparable和comparator都是用于比较数据大小,字母意思前者是形容词,而后者是名词。即实现comparable接口的类,具有了比较大小的功能。而实现comparator接口的类,是一个比较器。
在Collections工具类中,有一个排序方法sort,此方法可以传入一个集合,也可以传入一个集合和比较器。前者集合中的元素必须要实现comparable接口,而后者按照我们传入的comparator接口进行排序。

2. 返回值和排升/降序的联系

comparable接口方法是compareTo(T o)this对象和o对象的比较;
comparator接口方法是compare(T o1,T o2)o1对象和o2对象的比较;

方法的返回值代表的是o1(this)的顺序,而并非o1和o2的大小关系。只要返回负数,那么o1便在o2前方。返回正整数,o1在o2后方。

默认为升序排列。

在API中,明确表示出this(o1)减去o2。
故默认请求下,o1<o2时,才会返回负数。

如何设置使其降序排序?

若-(o1减去o2),便是降序排列。
我们可以将结果取反,那么排序,也是相反的,即为升序排序。

3. Lambda实现多条件排序

public class ListOrder {


    private static List<User> userList = new ArrayList<>();

    private static String DATA_FORMAT = "yyyy-MM-dd HH:mm";
    //已完成
    private static Integer END = 3;
    //进行中
    private static Integer ONDOING = 2;

    //构建数据
    static {
        Date date = new Date();

        Date d1 = DateUtils.addHours(date, -1);
        String s1 = DateFormatUtils.format(d1, DATA_FORMAT);
        User u1 = new User(2, s1);

        Date d2 = DateUtils.addHours(date, -3);
        String s2 = DateFormatUtils.format(d2, DATA_FORMAT);
        User u2 = new User(2, s2);

        Date d3 = DateUtils.addHours(date, -2);
        String s3 = DateFormatUtils.format(d3, DATA_FORMAT);
        User u3 = new User(3, s3);

        Date d4 = DateUtils.addHours(date, -2);
        String s4 = DateFormatUtils.format(d4, DATA_FORMAT);
        User u4 = new User(2, s4);

        Date d5 = DateUtils.addDays(date, -1);
        String s5 = DateFormatUtils.format(d5, DATA_FORMAT);
        User u5 = new User(3, s5);

        //进行中的要排在已完成的后面,两个模块再按时间排序
        userList.add(u1);
        userList.add(u2);
        userList.add(u3);
        userList.add(u4);
        userList.add(u5);
    }


    public static void main(String[] args) {
        //type字段升序排序,time字段升序排序。
        List<User> users2 = userList.stream().sorted(
                Comparator.comparing(User::getType).thenComparing(User::getTime))
                .collect(Collectors.toList());
        System.out.println(users2);
        //type字段升序排序,time字段降序排列。
        List<User> users = userList.stream().sorted(
                Comparator.comparing(User::getType).reversed()
                        .thenComparing(User::getTime).reversed())
                .collect(Collectors.toList());
        System.out.println(users);
        //Time字段降序排序,type字段降序排序。
        List<User> users3 = userList.stream().sorted(
                Comparator.comparing(User::getType).
                        thenComparing(User::getTime).reversed())
                .collect(Collectors.toList());
        System.out.println(users3);
        //type字段升序排序,time字段降序排序。
        List<User> users4 = userList.stream().
                sorted(Comparator.comparing(User::getType).reversed().
                        thenComparing(User::getTime)).
                collect(Collectors.toList());
        System.out.println(users4);
        /**
         * 第二种方式:o1(this)-o2便是升序排序,否则便是降序排序。
         */
        //按照type进行升序排序,按照time进行降序排序
        List<User> users5 = userList.stream().
                sorted(Comparator.comparing(User::getType).
                        thenComparing((o1, o2) -> o2.time.compareTo(o1.time)))
                .collect(Collectors.toList());
        System.out.println(users5);
        /**
         * 不借助stream也可以进行排序
         */
        userList.sort(Comparator.comparing(User::getType).reversed());
    }


    /**
     * 用户信息
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class User {
        private Integer type;
        private String time;
    }
}

若属性值为null,那么使用sorted进行排序时会出现空指针异常。解决方案:

        //getTime使用降序排列,若是time字段为null,那么排在首位
        userList.sort(Comparator.comparing(User::getTime,
                Comparator.nullsFirst(Comparator.reverseOrder())));
        System.out.println(userList);

推荐阅读

【java】Comparator的用法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。