
本文介绍如何利用泛型与函数式接口(如function)封装重复的stream操作,实现根据运行时输入(如字段名)动态选择键提取器和过滤条件,避免代码冗余,提升可维护性。
本文介绍如何利用泛型与函数式接口(如function)封装重复的stream操作,实现根据运行时输入(如字段名)动态选择键提取器和过滤条件,避免代码冗余,提升可维护性。
在实际开发中,我们常需对同一数据源(如 List
理想的解决方案是将“键提取逻辑”和“非空校验依据”抽象为参数,通过一个通用方法统一处理。核心思路是:使用 Function
以下是重构后的通用方法:
import org.springframework.util.ObjectUtils;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class CarStreamUtils {
/**
* 根据指定键提取器,对Car列表构建去重合并的Map
* @param carList 待处理的Car列表
* @param keyMapper 键提取函数(如 Car::getCarNumber),同时用于非空过滤
* @param <t> 键的类型(如 Long, String)
* @return 按指定字段聚合的Map,冲突时合并engineNumber
*/
public static <t> Map<t car> collectCars(List<car> carList, Function<car t> keyMapper) {
return carList.stream()
.filter(car -> !ObjectUtils.isEmpty(keyMapper.apply(car))) // 统一判空依据
.collect(Collectors.toMap(
keyMapper,
Function.identity(),
(x1, x2) -> new Car(
// 注意:此处需根据实际业务决定合并策略
// 示例中仅演示 engineNumber 拼接,其他字段建议保留x1或明确规则
x1.getCarId(),
(T) x1.getCarNumber(), // 类型安全需谨慎,见下方说明
x1.getCarColorId(),
x1.getEngineNumber().concat(x2.getEngineNumber()),
x1.getPartsNumber(),
x1.getModifiedBy()
)
));
}
}</car></car></t></t></t>
✅ 使用示例:
// 动态选择字段:传入对应getter方法引用即可
Map<long car> byColorId = CarStreamUtils.collectCars(carList, Car::getCarColorId);
Map<long car> byCarNumber = CarStreamUtils.collectCars(carList, Car::getCarNumber);
Map<string car> byEngine = CarStreamUtils.collectCars(carList, Car::getEngineNumber);
System.out.println("By color ID: " + byColorId.keySet()); // [1000, 2000]
System.out.println("By car number: " + byCarNumber.keySet()); // [100, 200]</string></long></long>
⚠️ 重要注意事项:
-
合并逻辑需严谨:原答案中 (x1, x2) -> new Car(x1.getCarColorId(), ...) 硬编码了 carColorId,但该方法应适配任意字段。实践中建议:
- 若仅需 engineNumber 合并,其他字段保留首个对象值(如 x1),则构造函数需显式传入全部字段;
- 或改用 Map
> 先分组,再由业务层决定合并策略,更灵活安全。
-
类型安全提醒:泛型
在运行时被擦除,keyMapper.apply(car) 返回值需确保能安全转换为 Car 构造所需类型(如 Long 字段不能传给 String 构造参数),建议配合 @SuppressWarnings("unchecked") 或重构为 Builder 模式增强可读性。 - 空值处理:ObjectUtils.isEmpty() 支持 null、空字符串、空集合等,优于 != null,但需引入 Spring Core 依赖;若无该依赖,可用 Objects.nonNull() + 自定义字符串/集合判空逻辑替代。
? 进阶提示(策略模式扩展):
可进一步封装为 CarAggregationStrategy
这种函数式抽象不仅消除了样板代码,更使业务逻辑与数据处理解耦,是 Java 8+ 流式编程的最佳实践之一。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











