我有以下代码在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 举报,一经查实,本站将立刻删除。