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

前言

之前在给一个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);

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/131152763
今日推荐