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

https://blog.csdn.net/qq_28165595/article/details/131152763

 

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

 

posted @ 2024-04-07 15:09  kelelipeng  阅读(65)  评论(0编辑  收藏  举报