如何通过一次Stream操作获取集合中对象的两个去重字段集合
一次Stream操作获取去重的VehicleType和regCode集合
要通过单次Stream遍历得到去重的VehicleType集合和regCode集合,可以根据Java版本选择不同的实现方式:
方案一:使用Java 12+的Collectors.teeing(推荐)
teeing收集器允许在一次流处理中同时应用两个下游收集器,最后合并结果,完美匹配需求:
首先确保Vehicle类有对应的getter方法:
class Vehicle { VehicleType type; String regCode; public VehicleType getType() { return type; } public String getRegCode() { return regCode; } } enum VehicleType { CAR, BUS }
然后执行Stream操作:
import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; // 也可使用其他Pair实现,比如javafx.util.Pair List<Vehicle> vehicles = List.of( new Vehicle() {{ type = VehicleType.CAR; regCode = "AB11"; }}, new Vehicle() {{ type = VehicleType.BUS; regCode = "XY12"; }}, new Vehicle() {{ type = VehicleType.CAR; regCode = "AB22"; }}, new Vehicle() {{ type = VehicleType.BUS; regCode = "AB22"; }} ); Pair<Set<VehicleType>, Set<String>> result = vehicles.stream() .collect(Collectors.teeing( // 第一个收集器:提取并去重VehicleType Collectors.mapping(Vehicle::getType, Collectors.toSet()), // 第二个收集器:提取并去重regCode Collectors.mapping(Vehicle::getRegCode, Collectors.toSet()), // 合并两个结果为Pair Pair::of )); // 输出结果示例:Pair{left=[CAR, BUS], right=[AB11, XY12, AB22]} System.out.println(result);
方案二:自定义收集容器(兼容Java 8及以上)
如果使用Java版本低于12,可以自定义一个收集容器,在单次遍历中同时收集两种数据:
import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.lang3.tuple.Pair; // 自定义收集容器 class VehicleStats { private final Set<VehicleType> types = new HashSet<>(); private final Set<String> regCodes = new HashSet<>(); // 累加单个Vehicle数据 public void accept(Vehicle vehicle) { types.add(vehicle.getType()); regCodes.add(vehicle.getRegCode()); } // 并行流场景下合并多个容器数据 public VehicleStats merge(VehicleStats other) { types.addAll(other.types); regCodes.addAll(other.regCodes); return this; } // 转换为需求的Pair格式 public Pair<Set<VehicleType>, Set<String>> toPair() { return Pair.of(types, regCodes); } } // 执行Stream操作 Pair<Set<VehicleType>, Set<String>> result = vehicles.stream() .collect( VehicleStats::new, VehicleStats::accept, VehicleStats::merge ).toPair();
两种方案都仅遍历一次Stream,满足“一次Stream操作”的要求,最终结果与预期格式一致。
内容的提问来源于stack exchange,提问作者Abbin Varghese
相关产品推荐
相关产品推荐

