微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 是否可以在收集器分组的情况下对每个List进行操作而不创建中间映射?

我有以下代码在List上执行分组,然后对每个分组列表进行操作,然后将其转换为单个项目:

Map<Integer,List<Record>> recordsGroupedById = myList.stream()
    .collect(Collectors.groupingBy(r -> r.get("complex_id")));

List<Complex> whatIwant = recordsGroupedById.values().stream().map(this::toComplex)
    .collect(Collectors.toList());

toComplex函数如下所示:

Complex toComplex(List<Record> records);

我觉得我可以在不创建中间地图的情况下做到这一点,也许使用reduce.有任何想法吗?

输入流按照我想在流中顺序分组的元素进行排序.在正常的循环结构中,我能够确定下一组何时开始并在那时创建“复杂”.

解决方法

那么你可以避免使用Map(老实说!)并使用我的 StreamEx库在单一管道中执行所有操作:

List<Complex> result = StreamEx.of(myList)
        .sortedBy(r -> r.get("complex_id"))
        .groupRuns((r1,r2) -> r1.get("complex_id").equals(r2.get("complex_id")))
        .map(this::toComplex)
        .toList();

这里我们首先按complex_id对输入进行排序,然后使用groupRuns自定义中间操作,如果应用于两个相邻元素的给定BiPredicate返回true,则将相邻的stream元素组合到List.然后,您有一个列表流,这些列表映射到Complex对象流,最后收集到列表中.

实际上没有中间映射,groupRuns实际上是懒惰的(在顺序模式下,它一次只保留一个中间列表),它也很好地并行化.另一方面,我的测试表明,对于未排序的输入,这种解决方案比基于groupingBy的解决方案要慢,因为它涉及对整个输入进行排序.当然sortedBy(这只是排序的快捷方式(Comparator.comparing(…)))需要中间内存来存储输入.如果您的输入已经排序(或至少部分排序,因此Timsort可以快速执行),那么此类解决方案通常比groupingBy更快.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐