如何将Java循环实现的汽车数据聚合代码改写为Stream流?
Java Stream实现按CarNum分组并按车辆类型聚合生成Output对象
核心实现思路
通过Collectors.groupingBy按carNum分组,再结合Collectors.collectingAndThen将每个分组的Car列表转换为Output对象。提供两种实现方案,分别适配不同场景的性能和可读性需求。
方案1:单次遍历分组列表(性能优先,与原循环逻辑对齐)
这种方式和原有循环实现逻辑一致,仅遍历一次分组后的Car列表,避免多次流操作的额外开销,适合大数据量场景:
import java.util.*; import java.util.stream.Collectors; // 初始化车辆类型限定集合(建议定义为static final,保证复用性和查询性能) private static final Set<String> SEDAN_QUALIFIER_SET = new HashSet<>(Arrays.asList("Sedan", "Hatchback")); private static final Set<String> SUV_QUALIFIER_SET = new HashSet<>(Arrays.asList("SUV", "MPV")); private static final Set<String> TRUCK_QUALIFIER_SET = new HashSet<>(Arrays.asList("Van", "Truck", "Truck-LD")); public Map<Long, Output> convertToOutput(List<Car> cdList) { return cdList.stream() .collect(Collectors.groupingBy( Car::getCarNum, Collectors.collectingAndThen( Collectors.toList(), cars -> { Output output = new Output(); output.setCarNum(cars.get(0).getCarNum()); List<String> sedanEngines = new ArrayList<>(); List<String> suvCombined = new ArrayList<>(); List<String> truckCombined = new ArrayList<>(); // 单次遍历收集所有类型的目标数据 for (Car car : cars) { if (SEDAN_QUALIFIER_SET.contains(car.getCartype())) { sedanEngines.add(car.getCarEngine()); } else if (SUV_QUALIFIER_SET.contains(car.getCartype())) { suvCombined.add(car.getCarEngine() + "_" + car.getCarName()); } else if (TRUCK_QUALIFIER_SET.contains(car.getCartype())) { truckCombined.add(car.getCarEngine() + "_" + car.getCarName()); } } // 拼接字符串,空列表自动生成空字符串,符合预期输出 output.setCarCode(String.join(",", sedanEngines)); output.setCarNameWithEngine(String.join(",", suvCombined)); output.setCarChasisInfo(String.join(",", truckCombined)); return output; } ) )); }
方案2:多流遍历实现(可读性优先,适合小数据量)
如果分组数据量较小,可通过多次流操作分别过滤、映射各类车辆数据,代码结构更清晰:
public Map<Long, Output> convertToOutput(List<Car> cdList) { return cdList.stream() .collect(Collectors.groupingBy( Car::getCarNum, Collectors.collectingAndThen( Collectors.toList(), cars -> { Output output = new Output(); output.setCarNum(cars.get(0).getCarNum()); // 收集Sedan/Hatchback类型的engine字段 String sedanEngineStr = cars.stream() .filter(car -> SEDAN_QUALIFIER_SET.contains(car.getCartype())) .map(Car::getCarEngine) .collect(Collectors.joining(",")); // 收集SUV/MPV类型的engine_name拼接结果 String suvCombinedStr = cars.stream() .filter(car -> SUV_QUALIFIER_SET.contains(car.getCartype())) .map(car -> car.getCarEngine() + "_" + car.getCarName()) .collect(Collectors.joining(",")); // 收集Truck/Van/Truck-LD类型的engine_name拼接结果 String truckCombinedStr = cars.stream() .filter(car -> TRUCK_QUALIFIER_SET.contains(car.getCartype())) .map(car -> car.getCarEngine() + "_" + car.getCarName()) .collect(Collectors.joining(",")); output.setCarCode(sedanEngineStr); output.setCarNameWithEngine(suvCombinedStr); output.setCarChasisInfo(truckCombinedStr); return output; } ) )); }
关键注意事项
- 类方法依赖:确保
Car类存在对应的getter方法(getCarNum()、getCarEngine()、getCarName()、getCartype()),Output类提供无参构造和setter方法。 - 空值处理:两种方案均通过
Collectors.joining或String.join处理空列表,自动生成空字符串,完全匹配预期输出要求。 - 集合优化:车辆类型限定集合使用
HashSet保证O(1)的查询性能,定义为static final避免重复初始化。
内容的提问来源于stack exchange,提问作者Vamsi
相关产品推荐
相关产品推荐

