Java 8 Stream如何将List<Employee>转为Map<Integer,Set<Set<String>>>
Java 8 Stream实现员工手机号按项目分组并分区
类定义
class Employee{ private Integer employeeId; private Integer projectId; private String mobileNumbers; // 需配套提供getter方法:getProjectId()、getMobileNumbers() }
需求
将员工列表转换为Map<Integer, Set<Set<String>>>:
- 键:员工所属的
projectId - 值:该项目下所有员工的手机号集合,需先将逗号分隔的多手机号拆分为单个元素,再按每100个一组分区,最终存储为嵌套集合
Set<Set<String>>
当前问题
现有代码仅能实现Map<Integer, Set<String>>,存在两个核心缺陷:
- 无法将
mobileNumbers字段中逗号分隔的多手机号拆分为Set中的单个元素 - 无法实现每100个手机号一组的分区逻辑
示例
输入
Employee[employeeId=1,projectId=1,mobileNumbers="1111,2222"] Employee[employeeId=2,projectId=1,mobileNumbers="33333"] Employee[employeeId=3,projectId=2,mobileNumbers="44444,5555"]
预期输出
{1=[["1111","2222","33333"]], 2=[["44444","5555"]]}
现有代码
Map<Integer,Set<String>> result2=employeeList.stream() .collect( Collectors.groupingBy(Employee::getProjectId, Collectors.mapping(Employee::getMobileNumbers, Collectors.toSet())) );
解决方案
通过flatMap拆分手机号,结合collectingAndThen实现分区逻辑,完整代码如下:
import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class EmployeeProcessor { public static void main(String[] args) { List<Employee> employeeList = Arrays.asList( new Employee(1, 1, "1111,2222"), new Employee(2, 1, "33333"), new Employee(3, 2, "44444,5555") ); Map<Integer, Set<Set<String>>> result = employeeList.stream() // 拆分逗号分隔的手机号,过滤空串与空白值,转换为单手机号流 .flatMap(emp -> { if (emp.getMobileNumbers() == null || emp.getMobileNumbers().trim().isEmpty()) { return Stream.empty(); } return Arrays.stream(emp.getMobileNumbers().split(",")) .map(String::trim) .filter(s -> !s.isEmpty()); }) // 按projectId分组,先收集所有手机号去重,再执行分区 .collect(Collectors.groupingBy(Employee::getProjectId, Collectors.collectingAndThen(Collectors.toSet(), phoneSet -> { Set<Set<String>> partitionedSets = new HashSet<>(); List<String> phoneList = new ArrayList<>(phoneSet); // 每100个一组拆分集合 for (int i = 0; i < phoneList.size(); i += 100) { int endIndex = Math.min(i + 100, phoneList.size()); partitionedSets.add(new HashSet<>(phoneList.subList(i, endIndex))); } return partitionedSets; }))); System.out.println(result); } } // 补全Employee类的构造方法与getter class Employee { private Integer employeeId; private Integer projectId; private String mobileNumbers; public Employee(Integer employeeId, Integer projectId, String mobileNumbers) { this.employeeId = employeeId; this.projectId = projectId; this.mobileNumbers = mobileNumbers; } public Integer getProjectId() { return projectId; } public String getMobileNumbers() { return mobileNumbers; } }
代码说明
flatMap处理拆分:将每个员工的mobileNumbers按逗号分割,过滤空值与空白手机号,转换为单个手机号的流,解决多手机号拆分问题。- 分组后分区:通过
collectingAndThen先将同一项目下的所有手机号收集到Set中去重,再将该集合按每100个元素一组拆分,生成嵌套的Set<Set<String>>。 - 空值防护:增加了对
mobileNumbers为空的判断,避免空指针异常。
内容的提问来源于stack exchange,提问作者KFH
相关产品推荐
相关产品推荐

