You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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
}

代码逻辑解释:

  1. 初始映射:new HashMap<>()作为collectEntries的初始值,后续所有分组操作都会在这个映射上累加。
  2. 闭包参数:闭包的两个参数分别是:
    • entry:当前遍历到的data中的子列表(比如['A',15.2])
    • accumulatorMap:用于存储分组结果的累加器映射
  3. 变量提取:显式声明sector和temp变量,从当前entry中取出对应的值,方便理解每一步操作。
  4. 列表初始化:检查accumulatorMap中是否存在当前sector,不存在则存入空列表,避免后续添加元素时出现空指针。
  5. 添加元素:将当前temp添加到对应sector的列表中。
  6. 返回累加器:闭包必须返回accumulatorMap,这样collectEntries会带着这个更新后的映射处理下一个元素,最终返回完整的分组结果。

内容的提问来源于stack exchange,提问作者snbmt21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:17:32