如何通过一次Stream将List<User>转换为Map<String, List>?
单次遍历List生成目标Map的几种方案
嘿,多次遍历集合确实有点没必要,既浪费性能又不够优雅。咱们可以通过几种方式实现仅遍历一次就完成所有列表的收集,下面给你详细讲讲:
方案1:使用Java 12+的Collectors.teeing()
teeing收集器的作用是把流中的元素同时分发给两个不同的收集器,然后将两个收集器的结果合并。要处理三个字段,我们可以嵌套使用teeing:
import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 假设User类有对应的getName()、getAge()、getOrg()方法 Map<String, List<String>> targetMap = userList.stream() .collect(Collectors.teeing( // 第一个分支:收集names和ages Collectors.teeing( Collectors.mapping(User::getName, Collectors.toList()), Collectors.mapping(User::getAge, Collectors.toList()), (namesList, agesList) -> { Map<String, List<String>> tempMap = new HashMap<>(); tempMap.put("names", namesList); tempMap.put("age", agesList); return tempMap; } ), // 第二个分支:收集orgs Collectors.mapping(User::getOrg, Collectors.toList()), // 合并两个分支的结果 (tempMap, orgsList) -> { tempMap.put("org", orgsList); return tempMap; } ));
这个写法完全基于Stream API,代码风格统一,适合Java 12及以上版本的项目。
方案2:简单直接的forEach遍历(兼容所有Java版本)
如果你项目的Java版本低于12,这种方式最实用——初始化三个空列表,一次遍历就把所有字段值分别添加进去,最后组装成Map:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; List<String> names = new ArrayList<>(); List<String> ages = new ArrayList<>(); List<String> orgs = new ArrayList<>(); // 仅遍历一次userList userList.forEach(user -> { names.add(user.getName()); ages.add(user.getAge()); orgs.add(user.getOrg()); }); // 组装目标Map Map<String, List<String>> targetMap = new HashMap<>(); targetMap.put("names", names); targetMap.put("age", ages); targetMap.put("org", orgs);
这种方式代码直观易懂,没有版本限制,而且性能是最优的,因为没有Stream的额外开销。
方案3:自定义Collector(纯Stream风格,兼容低版本)
如果你偏好纯Stream API的写法,也可以自定义一个Collector来实现单次收集:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collector; Collector<User, ?, Map<String, List<String>>> multiFieldCollector = Collector.of( // 初始化容器:创建包含三个空列表的Map () -> { Map<String, List<String>> container = new HashMap<>(); container.put("names", new ArrayList<>()); container.put("age", new ArrayList<>()); container.put("org", new ArrayList<>()); return container; }, // 累加器:每个User元素添加到对应的列表中 (container, user) -> { container.get("names").add(user.getName()); container.get("age").add(user.getAge()); container.get("org").add(user.getOrg()); }, // 组合器:并行流场景下合并多个容器(串行流不会用到) (container1, container2) -> { container1.get("names").addAll(container2.get("names")); container1.get("age").addAll(container2.get("age")); container1.get("org").addAll(container2.get("org")); return container1; } ); // 使用自定义Collector收集 Map<String, List<String>> targetMap = userList.stream().collect(multiFieldCollector);
这个自定义Collector完全符合Stream的设计思想,支持并行流处理,适合对代码风格有严格要求的场景。
内容的提问来源于stack exchange,提问作者Rinsen S
相关产品推荐
相关产品推荐

