Java8 将list分组并每组取一条记录

2020年02月15日 74点热度 0人点赞 0条评论

记录个实例,以备后用。

毕设中有一个功能是问卷/测试。在一定情况下用户可以提交多次,并且每次的提交记录都会保留,但是在汇总时,如果是问卷,只保留最新一个,如果是测试,保留得分最高的一个。

取每组的第一个值

由于从数据库取出时已经按提交时间倒序,所以取第一条记录即可。如果没有排序,可以参考下面取最大值的方法。

answerList= new ArrayList<>(answerList.stream().collect(Collectors.groupingBy(
        Answer::getUserId,
        Collectors.collectingAndThen(Collectors.toList(), v -> v.get(0))
)).values());

由于最后需要List类型,所以将Map转为了List。

取每组第一个的代码主要为

answerList.stream().collect(Collectors.groupingBy(
        Answer::getUserId,
        Collectors.collectingAndThen(Collectors.toList(), v -> v.get(0))
);

Collectors.groupingBy函数是用于分组的,第一个参数是key值,表示按照什么分组。

Collectors.collectingAndThen函数可以对每组内的元素进行处理,这里取了每组第一个元素。

取每组的最大值

answerList = new ArrayList<>(answerList.stream().collect(Collectors.toMap(
        Answer::getUserId,
        Function.identity(),
        (v1, v2) -> v1.getTotalScore() > v2.getTotalScore() ? v1 : v2)
).values());

由于最后需要List类型,所以将Map转为了List。

取每组最大值主要是这一部分

answerList.stream().collect(Collectors.toMap(
        Answer::getUserId,
        Function.identity(),
        (v1, v2) -> v1.getTotalScore() > v2.getTotalScore() ? v1 : v2)
)

Collectors.toMap可以将List转换成Map,第一个参数是key值,第二个参数是value值,Function.identity()等价于t -> t,第三个参数是当key冲突时的解决方法,可以通过这个参数来获取每个key对应的最大值。除此之外,也可以使用groupingBy+reduce来实现,不过稍微复杂点。

answerList.stream().collect(Collectors.groupingBy(
        Answer::getUserId,
        Collectors.collectingAndThen(
                Collectors.reducing((v1, v2) -> v1.getTotalScore() > v2.getTotalScore() ? v1 : v2),
                Optional::get
        )
));

likole

一个后端小白

文章评论