Java Streams:将Map按大写Key分组并合并List<Employee>值
解决Map键转大写并合并值列表的问题
方法一:使用Java 8+ Stream API(推荐)
如果你的项目使用Java 8及以上版本,Stream API可以简洁实现需求,避免嵌套列表和类型混乱:
Java 8兼容写法
import java.util.*; import java.util.stream.Collectors; public class Employee { private String id; private String name; public Employee(String id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "Employee{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } public static void main(String[] args) { // 构建原始分组Map Map<String, List<Employee>> originalMap = new HashMap<>(); originalMap.put("dept1", Arrays.asList(new Employee("1", "Alice"), new Employee("2", "Bob"))); originalMap.put("Dept1", Arrays.asList(new Employee("3", "Charlie"))); originalMap.put("dept2", Arrays.asList(new Employee("4", "David"))); // 转换键为大写并合并员工列表 Map<String, List<Employee>> resultMap = originalMap.entrySet().stream() // 将每个分组的员工拆分为「大写键-单个员工」的条目 .flatMap(entry -> entry.getValue().stream() .map(emp -> new AbstractMap.SimpleEntry<>(entry.getKey().toUpperCase(), emp))) // 按大写键分组,收集对应员工列表 .collect(Collectors.groupingBy( Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()) )); // 验证结果 resultMap.forEach((key, emps) -> System.out.println(key + ": " + emps)); } }
Java 9+简化写法
Java 9新增了Collectors.flatMapping,可以更直接地合并列表:
Map<String, List<Employee>> resultMap = originalMap.entrySet().stream() .collect(Collectors.groupingBy( entry -> entry.getKey().toUpperCase(), Collectors.flatMapping(entry -> entry.getValue().stream(), Collectors.toList()) ));
方法二:传统循环实现(兼容低版本Java)
如果项目需要兼容Java 8以下版本,用普通循环更稳妥:
import java.util.*; public class Employee { // 类定义同前... public static void main(String[] args) { Map<String, List<Employee>> originalMap = new HashMap<>(); // 初始化原始Map... Map<String, List<Employee>> resultMap = new HashMap<>(); for (Map.Entry<String, List<Employee>> entry : originalMap.entrySet()) { String upperKey = entry.getKey().toUpperCase(); // 不存在则创建新列表,存在则复用已有列表 List<Employee> targetList = resultMap.computeIfAbsent(upperKey, k -> new ArrayList<>()); // 合并当前分组的员工列表 targetList.addAll(entry.getValue()); } // 验证结果 resultMap.forEach((key, emps) -> System.out.println(key + ": " + emps)); } }
问题根源说明
你之前得到Map<Object, List<Object>>且值为嵌套列表,大概率是直接对原Map的entry按大写键分组,但没有将嵌套的List<Employee>拆平,而是直接收集整个列表,导致最终值类型变成List<List<Employee>>,同时因未指定泛型边界,被编译器推断为Object。上面的两种方法都通过拆平列表或直接合并的方式解决了这个问题。
内容的提问来源于stack exchange,提问作者Kishore Babu
相关产品推荐
相关产品推荐

