如何使用Java Stream从对象列表构造指定键值对的HashMap?
嘿,这两个Stream转Map的场景在Java开发里太常见了,我来给你详细拆解解法:
问题1:将Employee的id作为键、name作为值提取到HashMap
直接用Stream的collect方法结合Collectors.toMap就能轻松实现你要的效果,核心就是指定键和值的提取逻辑:
// 基础写法(默认返回普通Map,若需HashMap可看下方扩展) Map<Integer, String> idToNameMap = employees.stream() .collect(Collectors.toMap( Employee::getId, // 以Employee的id作为键 Employee::getName // 以Employee的name作为值 ));
注意事项:
- 如果你的
employees列表中存在重复id,上面的代码会抛出IllegalStateException,这时候可以传入第三个参数定义重复键的处理规则,比如保留旧值或新值:
// 重复键时保留旧值的写法 Map<Integer, String> idToNameMap = employees.stream() .collect(Collectors.toMap( Employee::getId, Employee::getName, (oldValue, newValue) -> oldValue // 自定义重复键处理逻辑 ));
- 如果需要明确返回
HashMap类型(默认返回的是通用Map实现),可以添加第四个参数指定Map的构造器:
Map<Integer, String> idToNameMap = employees.stream() .collect(Collectors.toMap( Employee::getId, Employee::getName, (oldValue, newValue) -> oldValue, HashMap::new // 指定返回HashMap ));
问题2:将Filter的keyword作为键、name作为值存入Map
这里因为每个Employee都包含一个List<Filter>,所以第一步需要用flatMap把所有Employee的Filter列表展平成一个单一的Stream<Filter>,之后再用toMap处理:
// 基础写法 Map<String, String> keywordToFilterNameMap = employees.stream() // 展平所有Employee的filters列表,得到所有Filter的流 .flatMap(employee -> employee.getFilters().stream()) .collect(Collectors.toMap( Filter::getKeyword, // 以Filter的keyword作为键 Filter::getName // 以Filter的name作为值 ));
注意事项:
- 和第一个问题一样,如果存在重复的keyword,会抛出异常,同样可以通过第三个参数处理:
// 重复keyword时保留第一个出现的name Map<String, String> keywordToFilterNameMap = employees.stream() .flatMap(employee -> employee.getFilters().stream()) .collect(Collectors.toMap( Filter::getKeyword, Filter::getName, (oldName, newName) -> oldName // 自定义重复键处理逻辑 ));
- 若要返回
HashMap,同样添加第四个参数:
Map<String, String> keywordToFilterNameMap = employees.stream() .flatMap(employee -> employee.getFilters().stream()) .collect(Collectors.toMap( Filter::getKeyword, Filter::getName, (oldName, newName) -> oldName, HashMap::new ));
内容的提问来源于stack exchange,提问作者takotsubo
相关产品推荐
相关产品推荐

