Groovy 映射
最后修改于 2025 年 3 月 20 日
Groovy 中的映射是键值集合,其中每个键映射到一个值。它们是动态的,允许您轻松添加或删除条目。本教程涵盖了创建映射、访问值以及执行遍历、排序和分组等操作,并附有示例来说明每个概念。
基础知识
映射使用方括号和冒号分隔的键值对定义。Groovy 提供了多种访问和修改它们的方法,使其能够高效地存储和检索数据。
def cts = [ sk: 'Slovakia', ru: 'Russia', de: 'Germany', no: 'Norway' ]
println cts['sk']
println cts.get('sk')
println cts.size()
cts.put('hu', 'Hungary')
println cts.containsKey('hu')
在此,cts 将国家代码映射到名称。您可以使用 ['key'] 或 get('key') 访问值,两者都返回 "Slovakia" for "sk"。size() 返回条目数。put('hu', 'Hungary') 添加一个新对,而 containsKey('hu') 检查 "hu" 是否存在,返回 true。这些方法展示了 Groovy 简洁的映射处理方式。
空映射和添加
您可以从一个空映射开始,然后动态地构建它,这是在数据逐步收集时的一种常见方法。
def map = [:] map['a'] = 1 map['b'] = 2 println map
[:] 创建一个空映射。使用 ['key'] = value,我们逐个添加条目。这将打印 [a:1, b:2],展示了映射如何灵活地增长,而无需预定义大小,这与数组不同。
遍历
遍历映射意味着迭代其条目。Groovy 提供了几种方法来循环遍历键和值,并可以选择包含索引以增加上下文。
def capitals = [ Bratislava: 424207, Vilnius: 556723, Lisbon: 564657,
Riga: 713016, Jerusalem: 780200, Warsaw: 1711324,
Budapest: 1729040, Prague: 1241664, Helsinki: 596661,
Tokyo: 13189000, Madrid: 3233527 ]
capitals.each { e ->
println "$e.key $e.value"
}
println "-----------------------------"
capitals.each { k, v ->
println "$k $v"
}
println "-----------------------------"
capitals.eachWithIndex { k, v, i ->
println "$i $k $v"
}
capitals 将城市名称映射到人口。第一个 each 使用 e 作为条目,访问 e.key 和 e.value。第二个将参数命名为 k 和 v 以示清晰。eachWithIndex 添加了 i,为每个条目编号。这些变体展示了 Groovy 灵活的迭代方式,让您可以选择最适合您需求的方式。
排序
对映射进行排序会根据键或值重新排列其条目。Groovy 的 sort 方法返回一个新的已排序映射,而原始映射保持不变,并支持通过闭包进行自定义比较。
def capitals = [ Bratislava: 424207, Vilnius: 556723, Lisbon: 564657,
Riga: 713016, Jerusalem: 780200, Warsaw: 1711324,
Budapest: 1729040, Prague: 1241664, Helsinki: 596661,
Tokyo: 13189000, Madrid: 3233527 ]
println capitals.sort { it.key }
println capitals.sort { it.value }
println capitals.sort { a, b -> b.value <=> a.value }
sort { it.key } 按城市名称字母顺序排序。sort { it.value } 按人口升序排序。sort { a, b -> b.value <=> a.value } 使用宇宙飞船运算符 (<=>) 按人口降序排序。原始的 capitals 映射不会被更改;每次调用都会生成一个新的已排序映射,展示了 Groovy 函数式的排序方法。
查找
Groovy 的 find 和 findAll 方法搜索映射(通常是映射的映射),查找匹配条件的条目,分别返回第一个匹配项或所有匹配项。这些对于查询数据非常强大。
def users = [
[fname: "Robert", lname: "Novak", salary: 1770],
[fname: "John", lname:"Doe", salary: 1230],
[fname: "Lucy", lname:"Novak", salary: 670],
[fname: "Ben", lname:"Walter", salary: 2050],
[fname: "Robin",lname: "Brown", salary: 2300],
[fname: "Amy",lname: "Doe", salary: 1250],
[fname: "Joe", lname:"Draker", salary: 1190],
[fname: "Janet", lname:"Doe", salary: 980],
[fname: "Peter",lname: "Novak", salary: 990],
[fname:"Albert", lname:"Novak",salary: 193]
]
println users.find { u -> u.salary < 1000 }
println users.findAll { u -> u.salary < 1000 }
users 是一个映射列表,每个映射代表一个人。find { u -> u.salary < 1000 } 返回第一个薪资低于 1000 的用户(Lucy)。findAll 返回所有符合条件的此类用户(Lucy、Janet、Peter、Albert)。这些方法使用闭包来定义条件,使其能够适应您需要搜索的任何标准。
计数
count 和 countBy 方法根据条件对映射或映射列表中的条目进行计数,从而无需手动迭代即可快速汇总数据。
def users = [
[fname: "Robert", lname: "Novak", salary: 1770],
[fname: "John", lname:"Doe", salary: 1230],
[fname: "Lucy", lname:"Novak", salary: 670],
[fname: "Ben", lname:"Walter", salary: 2050],
[fname: "Robin",lname: "Brown", salary: 2300],
[fname: "Amy",lname: "Doe", salary: 1250],
[fname: "Joe", lname:"Draker", salary: 1190],
[fname: "Janet", lname:"Doe", salary: 980],
[fname: "Peter",lname: "Novak", salary: 990],
[fname:"Albert", lname:"Novak",salary: 193]
]
println users.count { u -> u.lname == 'Novak' || u.lname == 'Doe' }
println users.countBy { u -> u.salary < 1000 }
count { u -> u.lname == 'Novak' || u.lname == 'Doe' } 计算姓氏为“Novak”或“Doe”的用户(共 7 人)。countBy { u -> u.salary < 1000 } 按条件分组,返回一个包含 true(4 个)和 false(6 个)计数的映射。这些方法简化了数据分析,利用 Groovy 的闭包语法来实现自定义逻辑。
Collect & GroupBy
collect 将映射条目转换为新集合,而 groupBy 则根据标准将它们组织到子映射中。两者都是数据操作和重构的关键。
def users = [
[fname: "Robert", lname: "Novak", salary: 1770],
[fname: "John", lname: "Doe", salary: 1230],
[fname: "Lucy", lname: "Novak", salary: 670],
[fname: "Ben", lname: "Walter", salary: 2050],
[fname: "Robin",lname: "Brown", salary: 2300],
[fname: "Amy",lname: "Doe", salary: 1250],
[fname: "Joe", lname: "Draker", salary: 1190],
[fname: "Janet", lname: "Doe", salary: 980],
[fname: "Peter", lname: "Novak", salary: 990],
[fname: "Albert", lname: "Novak",salary: 193]
]
println users.groupBy { it.lname }
println '--------------------------'
println users.collect { [it.fname, it.lname, it.salary * 1.1] }
println '--------------------------'
println users.collect { ["$it.fname $it.lname", it.salary * 1.1] }
groupBy { it.lname } 按姓氏将 users 分成子列表,创建一个以姓氏为键、匹配用户列表为值的映射。collect { [it.fname, it.lname, it.salary * 1.1] } 将每个用户转换为一个列表,其中薪资增加 10%。collect { ["$it.fname $it.lname", it.salary * 1.1] } 类似,但将姓名合并为单个字符串。这些操作凸显了 Groovy 灵活重塑数据的能力。
来源
本教程通过实际示例探讨了 Groovy 映射。
作者
列出 所有 Groovy 教程。