1. 概述

Groovy 在 Java 的 Map 基础上进行了扩展,提供了更丰富的操作方法,比如 过滤、查找、排序 等功能。此外,Groovy 还支持多种简洁的方式来创建和操作 Map。

在本文中,我们将详细介绍 Groovy 中 Map 的使用方式,包括创建、添加、检索、删除、遍历、过滤、转换、分组和排序等常见操作。


2. 创建 Groovy Map

Groovy 提供了非常简洁的语法来创建 Map,使用 [k:v] 这种字面量形式,可以一行完成初始化。

创建空 Map

def emptyMap = [:]

创建带数据的 Map

def map = [name: "Jerry", age: 42, city: "New York"]

⚠️ 注意:Groovy 默认使用 LinkedHashMap 实现 Map,但你可以通过 as 运算符修改实现类型。


3. 添加元素

Groovy 支持多种方式添加键值对。

使用下标方式添加

def map = [name:"Jerry"]
map["age"] = 42

使用点号语法(类似 JS)

map.city = "New York"

✅ 推荐:Groovy 支持类似 Java Bean 的属性访问方式。

使用变量作为 key

def hobbyLiteral = "hobby"
def hobbyMap = [(hobbyLiteral): "Singing"]
map.putAll(hobbyMap)
assertTrue(hobbyMap.hobby == "Singing")
assertTrue(hobbyMap[hobbyLiteral] == "Singing")

4. 获取元素

获取 Map 中的值也有两种方式:

使用下标访问

def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]
assertTrue(map["name"] == "Jerry")

使用点号访问

assertTrue(map.name == "Jerry")

⚠️ 注意:如果 key 不存在,返回 null,不会抛异常。


5. 删除元素

Groovy 提供了多个删除方法,可以根据 key 删除,也可以根据条件批量删除。

删除单个 key

def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]
map.remove(2)

批量删除(minus)

def minusMap = map.minus([2:42, 4:34])
assertTrue(minusMap == [1:20, a:30, ba:67, 6:39, 7:49])

条件删除(removeAll)

minusMap.removeAll{it -> it.key instanceof String}
assertTrue(minusMap == [1:20, 6:39, 7:49])

保留符合条件的条目(retainAll)

minusMap.retainAll{it -> it.value % 2 == 0}
assertTrue(minusMap == [1:20])

6. 遍历 Map

Groovy 提供了 each()eachWithIndex() 方法用于遍历 Map。

使用 each 遍历

map.each{entry -> println "$entry.key: $entry.value"}

使用 eachWithIndex 遍历(带索引)

map.eachWithIndex{entry, i -> println "$i $entry.key: $entry.value"}

单独获取 key 和 value

map.eachWithIndex{key, value, i -> println "$i $key: $value"}

7. 过滤 Map

Groovy 提供了多种过滤方法,如 find, findAll, grep, every, any 等。

示例数据

def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]

find - 找第一个符合条件的 Entry

assertTrue(map.find{it.value == "New York"}.key == "city")

findAll - 找出所有符合条件的 Entry

assertTrue(map.findAll{it.value == "New York"} == [city : "New York"])

grep - 返回 List 类型结果

map.grep{it.value == "New York"}.each{it -> assertTrue(it.key == "city" && it.value == "New York")}

every - 检查是否所有 Entry 都满足条件

assertTrue(map.every{it -> it.value instanceof String} == false)

any - 检查是否有 Entry 满足条件

assertTrue(map.any{it -> it.value instanceof String} == true)

8. 转换和收集 Map

Groovy 提供了 collectcollectEntries 方法,用于对 Map 的条目进行转换。

示例数据

def map = [
  1: [name:"Jerry", age: 42, city: "New York"],
  2: [name:"Long", age: 25, city: "New York"],
  3: [name:"Dustin", age: 29, city: "New York"],
  4: [name:"Dustin", age: 34, city: "New York"]
]

collect - 转换为 List

def names = map.collect{entry -> entry.value.name}
assertTrue(names == ["Jerry", "Long", "Dustin", "Dustin"])

collect - 指定集合类型(如 HashSet)

def uniqueNames = map.collect([] as HashSet){entry -> entry.value.name}
assertTrue(uniqueNames == ["Jerry", "Long", "Dustin"] as Set)

collectEntries - 转换为新 Map

def idNames = map.collectEntries{key, value -> [key, value.name]}
assertTrue(idNames == [1:"Jerry", 2:"Long", 3:"Dustin", 4:"Dustin"])

组合使用 find + collect

def below30Names = map.findAll{it.value.age < 30}.collect{key, value -> value.name}
assertTrue(below30Names == ["Long", "Dustin"])

9. 分组 Map

Groovy 提供了 groupBysubMap 方法用于对 Map 进行分组。

groupBy - 按条件分组

def map = [1:20, 2: 40, 3: 11, 4: 93]
def subMap = map.groupBy{it.value % 2}
assertTrue(subMap == [0:[1:20, 2:40], 1:[3:11, 4:93]])

subMap - 按 key 指定子集

def keySubMap = map.subMap([1,2])
assertTrue(keySubMap == [1:20, 2:40])

10. 排序 Map

Groovy 提供了 sort() 方法,可用于根据 key、value 或两者排序。

示例数据

def map = [ab:20, a: 40, cb: 11, ba: 93]

默认排序(按 key 自然排序)

def naturallyOrderedMap = map.sort()
assertTrue([a:40, ab:20, ba:93, cb:11] == naturallyOrderedMap)

自定义比较器排序

def compSortedMap = map.sort({k1, k2 -> k1 <=> k2} as Comparator)
assertTrue([a:40, ab:20, ba:93, cb:11] == compSortedMap)

按 value 排序

def cloSortedMap = map.sort({it1, it2 -> it1.value <=> it2.value})
assertTrue([cb:11, ab:20, a:40, ba:93] == cloSortedMap)

11. 总结

本文介绍了 Groovy 中 Map 的多种操作方式,包括:

  • 创建、添加、获取、删除
  • 遍历、过滤、转换
  • 分组、排序等高级操作

这些方法大大简化了我们在日常开发中对 Map 的处理,让代码更简洁、可读性更强。

如需完整示例代码,欢迎查看 GitHub 项目


原始标题:Maps in Groovy | Baeldung