如何在Groovy中使用collectEntries创建键对应多值的映射
用Groovy的collectEntries实现数据分组
我有一个格式为[String, Double]的嵌套列表:
def data = [ ['A', 15.2], ['A', 14.7], ['B', 6.54], ['A', 4.5], ['A', 16.8], ['A', 7.7], ['C', 1.5], ['B', 13.1], ['B', 6], ['C', 10.1] ]
我希望生成一个映射,将每个字符串类型的sector作为键,关联对应的多个double类型温度值。
我已经通过.each遍历数据实现了预期输出:
Map<String, List<BigDecimal>> groupedData = new HashMap<>() data.each {it -> String sector = it[0] BigDecimal temp = it[1] if(!groupedData.containsKey(sector)) { groupedData.put(sector, []) } groupedData.get(sector).add(temp) }
作为Groovy新手,我想了解是否仅使用collectEntries就能实现相同输出。我知道Groovy不需要显式变量声明,但请在解释中包含它们,以便我完全理解代码逻辑。
解决方案:用collectEntries的累加器模式实现
可以通过collectEntries的重载方法(带初始累加映射)来实现,逻辑和你原来的.each写法一致,但更贴合Groovy的函数式风格:
// 初始化分组映射,用collectEntries完成遍历和累加 Map<String, List<BigDecimal>> groupedData = data.collectEntries(new HashMap<>()) { entry, accumulatorMap -> // 从当前子列表中取出sector和温度值,显式声明变量 String sector = entry[0] BigDecimal temp = entry[1] // 如果累加映射中没有当前sector的键,初始化空列表 if (!accumulatorMap.containsKey(sector)) { accumulatorMap.put(sector, []) } // 将当前温度值添加到对应sector的列表中 accumulatorMap.get(sector).add(temp) // 返回累加映射,供下一个元素继续使用 accumulatorMap }
代码逻辑解释:
- 初始映射:
new HashMap<>()作为collectEntries的初始值,后续所有分组操作都会在这个映射上累加。 - 闭包参数:闭包的两个参数分别是:
entry:当前遍历到的data中的子列表(比如['A',15.2])accumulatorMap:用于存储分组结果的累加器映射
- 变量提取:显式声明
sector和temp变量,从当前entry中取出对应的值,方便理解每一步操作。 - 列表初始化:检查
accumulatorMap中是否存在当前sector,不存在则存入空列表,避免后续添加元素时出现空指针。 - 添加元素:将当前
temp添加到对应sector的列表中。 - 返回累加器:闭包必须返回
accumulatorMap,这样collectEntries会带着这个更新后的映射处理下一个元素,最终返回完整的分组结果。
内容的提问来源于stack exchange,提问作者snbmt21
相关产品推荐
相关产品推荐

