项目中遇到一个需求,需要把sql中查出的数据,进行复杂计算后,进行多条件排序(只用sql无法做到)。因此用到了java8 Stream中的sort来解决,这篇文章的用途,是为了让更多需要用到多条件排序的人可以迅速上手。
一、案例
pojo
@Data
public class TestInfo {
private Long id;
private String name;
private Integer score;
private Integer onJobMonth;
private Integer lastScore;
}
排序需求
对员工评分进行排序。评分高者在前,评分相同者,在司工龄长的在前,评分与工龄都相同的,上月评分高的在前。
排序数据及写法
姓名 | 评分 | 工龄(月) | 上月评分 |
---|
张三 | 10 | 1 | 0 | 李四 | 20 | 3 | 10 | 王五 | 100 | 22 | 90 | 赵六 | 100 | 32 | 100 | 腾七 | 100 | 31 | 100 | 加斯滕 | 60 | 12 | 30 | 马佳佳 | 60 | 12 | 40 | 巴神 | 60 | 3 | 20 |
List<TestInfo> testInfos = buildTestInfo();
List<TestInfo> sortList = testInfos.stream().sorted(
Comparator.comparing(TestInfo::getLastScore, Comparator.reverseOrder())
.thenComparing(TestInfo::getOnJobMonth, Comparator.reverseOrder())
.thenComparing(TestInfo::getScore, Comparator.reverseOrder())).collect(Collectors.toList());
sortList.forEach(System.out::println);
TestInfo(id=4, name=赵六, score=100, onJobMonth=32, lastScore=100)
TestInfo(id=5, name=腾七, score=100, onJobMonth=31, lastScore=100)
TestInfo(id=3, name=王五, score=100, onJobMonth=22, lastScore=90)
TestInfo(id=8, name=马佳佳, score=60, onJobMonth=12, lastScore=40)
TestInfo(id=6, name=加斯滕, score=60, onJobMonth=12, lastScore=30)
TestInfo(id=7, name=巴神, score=60, onJobMonth=3, lastScore=20)
TestInfo(id=2, name=李四, score=20, onJobMonth=3, lastScore=10)
TestInfo(id=1, name=张三, score=10, onJobMonth=1, lastScore=0)
由排序结果可知,在sort中,代码逻辑中,将需求的排序顺序翻转即可达到效果。至于原因,看到这里的朋友,脑补下每次的排序结果,就能理解了。
二、关于Comparator
Comparator的thenComparing用在comparing及相关方法之后, 是以上次排序为结果进行再排序。 thenComparing和comparing的参数相同,都为(Function keyExtractor)和(Function keyExtractor,Comparator keyComparator),其中java.util.function.Function为java8引入的函数式接口(这里不讨论自定义比较器),而第二个参数为排序方式,java8的Comparator有提供多种排序方式。
方法名 | 含义 |
---|
reverseOrder | 自然顺序倒叙排序 | naturalOrder | 自然顺序正序排序 | nullsFirst | 自然顺序排序,如果有null,则null在最前(如果上面案例用name排序,且有人name为null,则上面的自然排序会报错) | nullsLast | 自然顺序排序,如果有null,则null在最后(与nullsFirst类似) |
对于reverseOrder方法,有另一种写法,如:Comparator.comparing(TestInfo::getLastScore, Comparator.reverseOrder())还可以写为Comparator.comparing(TestInfo::getLastScore).reversed()。
|