Java 8使用Stream流实现List转Map(键为字符串值为长度)
问题背景
- 现有一个存储
String类型元素的list - 需求:将每个字符串作为key,对应字符串的长度作为value存入
Map(如HashMap) - 已知约束:List内所有字符串均唯一,不存在重复key场景
用户当前编写的无法正常运行的代码如下:
List<String> ls = Arrays.asList("James", "Sam", "Scot", "Elich"); Map<String,Integer> map = new HashMap<>(); Function<String, Map<String, Integer>> fs = new Function<>() { @Override public Map<String, Integer> apply(String s) { map.put(s,s.length()); return map; } }; Map<String, Integer> nmap = ls .stream() .map(fs) .collect(Collectors.toMap()); // 此处卡壳无法实现 System.out.println(nmap);
错误原因
你的实现逻辑完全偏离了Stream API的设计:
Stream.map()的作用是将流中每个元素转换为另一个类型的单个元素,你当前的写法会把每个字符串都转换为同一个外部共享的HashMap实例,最终流内存储的是多个指向同一个Map的引用,根本无法通过toMap()收集得到你要的键值对结构。- 在Stream操作中修改外部共享变量属于带副作用的写法,并行流场景下会出现线程安全问题,不符合函数式编程的规范。
最简实现
因为不存在重复key,直接调用Collectors.toMap()的双参数重载即可,不需要额外定义中间Function、不需要提前初始化Map:
List<String> ls = Arrays.asList("James", "Sam", "Scot", "Elich"); Map<String, Integer> nmap = ls.stream() .collect(Collectors.toMap( str -> str, // key为字符串本身 String::length // value为字符串长度 )); System.out.println(nmap);
运行输出:
{James=5, Scot=4, Elich=5, Sam=3}
如果你确实要使用map中间操作(属于冗余写法,不推荐),可以先将每个字符串转换为键值对Entry,再统一收集:
List<String> ls = Arrays.asList("James", "Sam", "Scot", "Elich"); Map<String, Integer> nmap = ls.stream() .map(str -> new AbstractMap.SimpleEntry<>(str, str.length())) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue ));
该写法最终效果和最简实现完全一致,只是多了一步创建Entry对象的开销,日常开发优先选择第一种写法。
内容的提问来源于stack exchange,提问作者SUVAM ROY
相关产品推荐
相关产品推荐

