如何将单个Stream<Acknowledgement>流按两个过滤条件拆分为两个列表
异常原因
- Java Stream被设计为仅可执行一次终端操作的对象,一旦调用
collect()/count()/forEach()等终端操作,流就会被标记为已关闭,无法复用。 - 你的代码连续两次对同一个
mappedRecords流执行collect()操作,第二次操作时流已经被关闭,因此抛出对应的非法状态异常。
最优实现方案
推荐使用Collectors.groupingBy一次性按reportType分组,仅需遍历一次流即可得到两类结果,性能优于先收集全量列表再两次过滤的方案:
import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 一次性按reportType分组所有元素 Map<String, List<Acknowledgement>> reportTypeMap = mappedRecords .collect(Collectors.groupingBy(Acknowledgement::getReportType)); // 从分组结果中直接取出对应类型的列表,不存在则返回空列表 List<Acknowledgement> summaryList = reportTypeMap.getOrDefault(summaryReportType, Collections.emptyList()); List<Acknowledgement> detailList = reportTypeMap.getOrDefault(detailReportType, Collections.emptyList());
备选方案(适合数据量较小的场景)
如果业务场景需要保留全量原始数据,也可以先把原流所有元素收集为一个中间列表,再基于该列表生成两次新流分别过滤:
// 先把原流所有元素落地为中间列表 List<Acknowledgement> allRecords = mappedRecords.collect(Collectors.toList()); List<Acknowledgement> summaryList = allRecords.stream() .filter(x -> x.getReportType().equals(summaryReportType)) .collect(Collectors.toList()); List<Acknowledgement> detailList = allRecords.stream() .filter(x -> x.getReportType().equals(detailReportType)) .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者navig8tr
相关产品推荐
相关产品推荐

