如何使用Java Stream过滤返回null的元素?求最佳实践
Java Stream跨列表过滤的最佳实践
先给你指出原代码里的几个明显错误:
- 类名拼写错误:
Objet应该是Object - 方法调用错误:
list2()是无效调用,直接用参数list2就行 - 过滤逻辑写错了:第二个
filter里没正确接收findRelevantObject的返回值,原代码里的判断逻辑完全不成立 - 方法参数类型错误:
findRelevantObject的第二个参数应该是List<Object2>而非List<list2>
下面是这类跨列表过滤场景的最佳实践,核心是先预处理list2,避免重复遍历浪费性能,再结合Stream完成逻辑:
步骤1:预处理list2,构建ID的有效性映射
原逻辑要判断list2中同id的所有对象是否都满足isToChangeNum == 1,可以先把list2按id分组,提前计算每个id的有效性:
// 预处理:key是Object2的id,value是该id下所有对象是否都符合条件 Map<Long, Boolean> idValidMap = list2.stream() .collect(Collectors.groupingBy( Object2::getId, Collectors.mapping(Object2::isToChangeNum, Collectors.allMatch(num -> num == 1)) ));
这样后续过滤时直接查map就行,不用每次都遍历整个list2,时间复杂度从O(n*m)降到O(n+m),数据量大时性能提升特别明显。
步骤2:用Stream完成过滤收集
基于预处理好的映射,写清晰的过滤逻辑:
List<Object> res = list.stream() // 第一个条件:状态为OLD .filter(x -> x.getStatus() == Status.OLD) // 第二个条件:id在映射中存在且有效 .filter(x -> idValidMap.getOrDefault(x.getId(), false)) .collect(Collectors.toList());
为什么这是最佳实践?
- 性能更优:只遍历list2一次,避免嵌套遍历的性能浪费
- 逻辑清晰:每个filter只做单一判断,读代码的人一眼就能看懂
- 减少冗余:不需要额外写
findRelevantObject方法,逻辑直接内嵌在流操作里
简化版(仅适用于小数据量)
如果list2的数据量极小,性能不是优先考虑项,也可以直接写嵌套流,但大数据量场景别用:
List<Object> res = list.stream() .filter(x -> x.getStatus() == Status.OLD) .filter(x -> list2.stream() .filter(m -> m.getId() == x.getId()) .allMatch(m -> m.isToChangeNum() == 1) ) .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

