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 教程。