Stream流sorted的多级排序问题(巨坑)

文章讨论了在Java中对List集合中的对象进行多属性排序时可能出现的问题,特别是使用Comparator和StreamAPI的情况。作者通过一个学生类示例,解释了如何正确实现先按年龄倒序,再按考试成绩倒序的排序逻辑,指出了在使用`reversed()`方法时的常见误区,并提供了四种不同排序方式的示例代码,帮助读者理解和避免排序陷阱。
摘要由CSDN通过智能技术生成

前言

之前在给一个List集合中对象进行多属性排序,比如先根据对象中的A属性正序排序,若两个对象的A属性值相同,再根据对象的B属性进行正序排序。这种排序在实际开发中比较常见,但是这里面有个坑。

举个例子

先初始化一个学生集合

        List<Student> studentArrayList = new ArrayList<>();
        studentArrayList.add(new Student("张三", 20, 34));
        studentArrayList.add(new Student("李四", 20, 35));
        studentArrayList.add(new Student("王五", 22, 34));
        studentArrayList.add(new Student("丁飞", 21, 23));
        studentArrayList.add(new Student("曹海", 22, 23));
        studentArrayList.add(new Student("徐风", 24, 234));

学生类如下

public class Student {
    private String name;
    private Integer age;
    private Integer testScore;
    
    public Student(String name, Integer age, Integer testScore) {
        this.name = name;
        this.age = age;
        this.testScore = testScore;
    }

    //省略set,get方法
}

如果我们要先根据学生年龄倒序排,再根据学生考试成绩倒序排,很多人可以直接写下这样的排序代码

List studentArraySortList = studentArrayList.stream().sorted(Comparator.comparingInt(Student::getAge).reversed(). 
          thenComparingInt(Student::getTestScore).reversed()).collect(Collectors.toList());

运行结果如下

[姓名=李四,年龄:20分数:35, 姓名=张三,年龄:20分数:34, 姓名=丁飞,年龄:21分数:23,
 姓名=王五,年龄:22分数:34, 姓名=曹海,年龄:22分数:23, 姓名=徐风,年龄:24分数:234]

很明显,这不是我们预期的效果

如何正确实现多级排序

我们先来看看reversed()方法的方法说明

 大致意思事说在当前的比较器基础上运行新的比较器。

 这里的reversed是运用于Comparator.comparingInt(Student::getAge).reversed().
thenComparingInt(Student::getTestScore)而不是thenComparingInt(Student::getTestScore),这样是不是很好理解了。所以我们要想先根据学生年龄倒序排,再根据学生考试成绩倒序排,应该这样写

List<Student> studentArraySortList = studentArrayList.stream().sorted(Comparator.comparingInt(Student::getAge).
               thenComparingInt(Student::getTestScore).reversed()).collect(Collectors.toList());

感兴趣的小伙伴可以测试下四种写法,对比下运行结果,加深理解


//先根据age正序排,再根据testScore正序排
studentArrayList.stream().sorted(Comparator.comparingInt(Student::getAge).
                thenComparingInt(Student::getTestScore)).collect(Collectors.toList()).forEach(System.out::println);


//先根据age倒序排,再根据testScore正序排
studentArrayList.stream().sorted(Comparator.comparingInt(Student::getAge).reversed().
                thenComparingInt(Student::getTestScore)).collect(Collectors.toList()).forEach(System.out::println);

//先根据age倒序排,再根据testScore倒序排
studentArrayList.stream().sorted(Comparator.comparingInt(Student::getAge).
                thenComparingInt(Student::getTestScore).reversed()).collect(Collectors.toList()).forEach(System.out::println);

//先根据age正序排,再根据testScore倒序排
studentArrayList.stream().sorted(Comparator.comparingInt(Student::getAge).reversed().
                thenComparingInt(Student::getTestScore).reversed()).collect(Collectors.toList()).forEach(System.out::println);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱琴孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值