Java Stream 实战:订单商品ID过滤技巧(由浅入深)
在电商系统开发中,我们经常需要根据订单项中的商品ID状态进行过滤处理。本文将详细介绍两种高频使用场景的实现方法,从基础到进阶,帮助你掌握Stream API的精髓。
一、基础场景:订单项中存在空商品ID的订单
原始写法(存在问题)
java
List<Order> collect = siteOrderList.stream().filter(order -> {
// 订单项中存在商品ID为空的
order.getOrderItems().stream().filter(item -> item.getSkuId() == null)
}).collect(Collectors.toList());
问题分析:filter()内部使用了无终止操作的stream,无法返回布尔值
正确实现
java
// 找出订单项中存在商品ID为空的订单
List<Order> ordersWithNullSku = siteOrderList.stream()
.filter(order -> order.getOrderItems().stream()
.anyMatch(item -> item.getSkuId() == null))
.collect(Collectors.toList());
关键点:
- 使用
anyMatch()替代filter()作为终端操作 anyMatch()返回boolean值,符合filter条件- 时间复杂度:O(n*m),n为订单数,m为订单项数
二、进阶场景:订单项中所有商品ID均非空
原始写法(不完整)
java
siteOrderList.stream().filter(order -> {
// 订单项中商品ID都不是空的
List<OrderItem> collect1 = order.getOrderItems().stream()
.filter(item -> item.getSkuId() != null)
.collect(Collectors.toList());
});
问题分析:缺少终端操作,collect未使用
正确实现
java
// 找出订单项中商品ID都不是空的订单
List<Order> ordersWithoutNullSku = siteOrderList.stream()
.filter(order -> order.getOrderItems().stream()
.allMatch(item -> item.getSkuId() != null))
.collect(Collectors.toList());
核心技巧:
- 使用
allMatch()确保所有元素满足条件 - 短路操作:遇到第一个不满足条件即终止
- 性能优于
noneMatch(item -> item.getSkuId() == null)
三、性能优化技巧
并行处理(大数据量场景)
java
List<Order> largeOrders = siteOrderList.parallelStream()
.filter(order -> order.getOrderItems().parallelStream()
.allMatch(item -> item.getSkuId() != null))
.collect(Collectors.toList());
适用场景:
- 订单量 > 10,000
- 多核CPU环境
- 注意:小数据量可能降低性能
缓存优化(重复过滤场景)
java
Map<Boolean, List<Order>> partitionedOrders = siteOrderList.stream()
.collect(Collectors.partitioningBy(order ->
order.getOrderItems().stream()
.allMatch(item -> item.getSkuId() != null)
));
List<Order> validOrders = partitionedOrders.get(true);
List<Order> invalidOrders = partitionedOrders.get(false);
优势:
- 单次遍历完成两种过滤
- 后续可直接使用分类结果
- 减少重复计算
四、实战应用示例
场景:订单校验系统
java
public Map<String, List<Order>> validateOrders(List<Order> orders) {
List<Order> validOrders = orders.stream()
.filter(order -> order.getOrderItems().stream()
.allMatch(item -> item.getSkuId() != null))
.collect(Collectors.toList());
List<Order> invalidOrders = orders.stream()
.filter(order -> order.getOrderItems().stream()
.anyMatch(item -> item.getSkuId() == null))
.collect(Collectors.toList());
return Map.of(
"valid", validOrders,
"invalid", invalidOrders
);
}
执行结果示例:
| 订单类型 | 数量 | 占比 |
|---|---|---|
| 有效订单 | 1,245 | 82.3% |
| 无效订单 | 270 | 17.7% |
五、最佳实践总结
-
匹配操作选择:
anyMatch():存在至少一个满足条件的元素allMatch():所有元素都满足条件noneMatch():没有元素满足条件
-
性能优化原则:
- 优先使用短路操作(anyMatch/allMatch)
- 大数据量考虑并行流
- 避免嵌套多层filter
-
可读性提升技巧:
java// 提取Predicate提升可读性 Predicate<OrderItem> hasValidSku = item -> item.getSkuId() != null; List<Order> validOrders = orders.stream() .filter(order -> order.getOrderItems().stream() .allMatch(hasValidSku)) .collect(Collectors.toList());
经验分享 :在实际项目中,这类过滤操作可封装为独立方法,结合Spring的
@Service注解实现复用。例如订单校验服务、库存预检服务等场景均可使用此模式。
通过掌握这些Stream API技巧,你可以显著提升订单处理逻辑的简洁性和执行效率,让代码既优雅又高效!