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);