Java 8如何使用Stream将Map<String,List<String>>转换为Map<String,String>
Java 8 Stream实现Map<大洲, List<城市>>的反向键值转换
你需要的本质是把原Map的键值做反向映射:原结构的键是大洲、值是该大洲下的城市列表,要转成以城市为键、所属大洲为值的Map,用Java 8 Stream的flatMap拆分数组 + Collectors.toMap收集即可。
完整可运行代码示例
import java.util.*; import java.util.stream.Collectors; public class MapConvert { public static void main(String[] args) { // 构造原Map结构 Map<String, List<String>> originMap = new HashMap<>(); originMap.put("North America", Arrays.asList("New York", "Vancouver")); originMap.put("Europe", Arrays.asList("London", "Paris")); // 转换逻辑 Map<String, String> resultMap = originMap.entrySet().stream() // 把每个大洲对应的城市列表拆分为单个<城市, 所属大洲>的键值对流 .flatMap(entry -> entry.getValue().stream() .map(city -> new AbstractMap.SimpleEntry<>(city, entry.getKey())) ) // 收集为目标Map .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, // 合并规则:如果出现重复城市名,默认保留先出现的大洲 // 若需要取后出现的,可改为 (existingVal, newVal) -> newVal (existingVal, newVal) -> existingVal, // 可选:指定结果Map的实现类,这里用LinkedHashMap保留插入顺序 LinkedHashMap::new )); // 输出结果完全符合预期结构 System.out.println(resultMap); // 输出:{New York=North America, Vancouver=North America, London=Europe, Paris=Europe} } }
核心逻辑说明
originMap.entrySet().stream():先把原Map的每个<大洲, 城市列表>entry转成流flatMap(...):核心拆分步骤,把每个大洲下的城市列表拆成独立元素,每个元素绑定「城市名」和「所属大洲」两个信息,合并为统一的流Collectors.toMap(...):把流里的所有键值对收集为目标Map:- 前两个参数分别指定从流元素取新Map的键、值的规则
- 第三个参数是重复键合并规则:如果不同大洲有同名城市,默认不指定规则时会直接抛
IllegalStateException,必须按业务指定合并策略 - 第四个参数可选,用来指定结果Map的实现类,比如需要并发就用
ConcurrentHashMap,不需要的话可省略,此时默认返回HashMap
健壮性优化提示
如果原Map的value(城市列表)可能为null,可以在flatMap前加空判断,避免抛空指针:
.flatMap(entry -> { List<String> cities = entry.getValue(); // 城市列表为null时返回空流,跳过该大洲 return cities == null ? Stream.empty() : cities.stream() .map(city -> new AbstractMap.SimpleEntry<>(city, entry.getKey())); })
内容的提问来源于stack exchange,提问作者andy666y
相关产品推荐
相关产品推荐

