ZetCode

Groovy 记录

最后修改于 2025 年 3 月 20 日

Groovy 4 引入了记录,这是一种创建不可变数据类的简洁方式。在记录之前,Groovy 提供了 @Immutable@Canonical 注解来实现类似的目的。

简单记录示例

这是一个基础的 Groovy 记录。将其保存为 SimpleRecord.groovy

SimpleRecord.groovy
record User(String fname, String lname, String occupation) { }

def u = new User('John', 'Doe', 'gardener')
println u 

println u.fname
println u.lname
println u.occupation

记录自动提供构造函数、getter 和 toString 方法。此示例创建了一个 User 记录并访问其字段。

$ groovy SimpleRecord.groovy
User(fname=John, lname=Doe, occupation=gardener)
John
Doe
gardener

命名参数构造函数

记录支持命名参数以实现灵活的实例化。

NamedArgsRecord.groovy
record User(String fname, String lname, String occupation) { }

def u = new User(lname:'Roe', fname:'Roger', occupation:'driver')
println u

使用命名参数,您可以按任意顺序指定字段。这提高了创建记录实例时的可读性和灵活性。

$ groovy NamedArgsRecord.groovy
User(fname=Roger, lname=Roe, occupation=driver)

解构记录

Groovy 允许将记录解构为单独的变量。

DestructureRecord.groovy
record User(String fname, String lname, String occupation) { }

def u = new User('John', 'Doe', 'gardener')
def (fname, lname, occupation) = u

println "${fname} ${lname} is a ${occupation}"

解构在一行中将记录字段分配给变量。在这里,我们提取字段并在格式化字符串中使用它们。

$ groovy DestructureRecord.groovy
John Doe is a gardener

可排序记录

可以使用 @Sortable 注解使记录可排序。

SortableRecord.groovy
import groovy.transform.Sortable

@Sortable(includes='lname')
record User(String fname, String lname, String occupation) {}

def users = [
    new User('John', 'Doe', 'gardener'),
    new User('Roger', 'Roe', 'driver'),
    new User('Lucia', 'Smith', 'accountant'),
    new User('Paul', 'Newman', 'firefighter'),
    new User('Adam', 'Clapton', 'teacher'),
    new User('Jane', 'Walter', 'pilot')
]

for (def user in users) {
    println user
}

println '----------------------'

users.sort()

for (def user in users) {
    println user
}

@Sortable 注解使记录可比较。在这里,我们按 lname 对用户进行排序,展示排序前后的用户。

$ groovy SortableRecord.groovy
User(fname=John, lname=Doe, occupation=gardener)
User(fname=Roger, lname=Roe, occupation=driver)
User(fname=Lucia, lname=Smith, occupation=accountant)
User(fname=Paul, lname=Newman, occupation=firefighter)
User(fname=Adam, lname=Clapton, occupation=teacher)
User(fname=Jane, lname=Walter, occupation=pilot)
----------------------
User(fname=Adam, lname=Clapton, occupation=teacher)
User(fname=John, lname=Doe, occupation=gardener)
User(fname=Paul, lname=Newman, occupation=firefighter)
User(fname=Roger, lname=Roe, occupation=driver)
User(fname=Lucia, lname=Smith, occupation=accountant)
User(fname=Jane, lname=Walter, occupation=pilot)

分组记录

可以使用 Groovy 的 groupBy 方法对记录进行分组。

GroupRecord.groovy
import java.time.LocalDate

record User(String name, String occupation, LocalDate dob) { }

def users = [
    new User('John Doe', 'gardener', LocalDate.parse('1973-09-07')),
    new User('Roger Roe', 'driver', LocalDate.parse('1963-03-30')),
    new User('Kim Smith', 'teacher', LocalDate.parse('1980-05-12')),
    new User('Joe Nigel', 'artist', LocalDate.parse('1983-03-30')),
    new User('Liam Strong', 'teacher', LocalDate.parse('2009-03-06')),
    new User('Robert Young', 'gardener', LocalDate.parse('1978-11-16')),
    new User('Liam Strong', 'teacher', LocalDate.parse('1986-10-23'))
]
 
def res = users.groupBy({ it.occupation })

for (def e in res) {
    println e
}

此示例按职业对用户进行分组。groupBy 方法返回一个映射,其中键是职业,值是用户列表。

$ groovy GroupRecord.groovy
gardener=[User(name=John Doe, occupation=gardener, dob=1973-09-07), User(name=Robert Young, occupation=gardener, dob=1978-11-16)]
driver=[User(name=Roger Roe, occupation=driver, dob=1963-03-30)]
teacher=[User(name=Kim Smith, occupation=teacher, dob=1980-05-12), User(name=Liam Strong, occupation=teacher, dob=2009-03-06), User(name=Liam Strong, occupation=teacher, dob=1986-10-23)]
artist=[User(name=Joe Nigel, occupation=artist, dob=1983-03-30)]

带记录的自定义静态工厂

记录可以包含静态方法,就像此示例按千禧一代状态拆分用户一样。

StaticFactoryRecord.groovy
import java.time.LocalDate

record User(String name, String occupation, LocalDate dob) { 
    static User of(String name, String occupation, LocalDate dob) {
        return new User(name, occupation, dob)
    }
}

def users = [
    User.of('John Doe', 'gardener', LocalDate.parse('1973-09-07')),
    User.of('Roger Roe', 'driver', LocalDate.parse('1963-03-30')),
    User.of('Kim Smith', 'teacher', LocalDate.parse('1980-05-12')),
    User.of('Joe Nigel', 'artist', LocalDate.parse('1983-03-30')),
    User.of('Liam Strong', 'teacher', LocalDate.parse('2009-03-06')),
    User.of('Robert Young', 'gardener', LocalDate.parse('1978-11-16')),
    User.of('Liam Strong', 'teacher', LocalDate.parse('1986-10-23'))
]

def millen = LocalDate.parse('2000-01-01')
def res = users.groupBy({ it.dob > millen })

println 'millennials'
for (def e in res[true]) {
    println e
}

println 'others'
for (def e in res[false]) {
    println e
}

静态 of 方法提供了替代的构造函数。我们使用它来按 2000 年后出生(千禧一代)的用户与其他用户进行分组。

$ groovy StaticFactoryRecord.groovy
millennials
User(name=Liam Strong, occupation=teacher, dob=2009-03-06)
others
User(name=John Doe, occupation=gardener, dob=1973-09-07)
User(name=Roger Roe, occupation=driver, dob=1963-03-30)
User(name=Kim Smith, occupation=teacher, dob=1980-05-12)
User(name=Joe Nigel, occupation=artist, dob=1983-03-30)
User(name=Robert Young, occupation=gardener, dob=1978-11-16)
User(name=Liam Strong, occupation=teacher, dob=1986-10-23)

来源

Groovy 文档

本教程涵盖了 Groovy 记录的要点和示例。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有八年以上经验。

列出 所有 Groovy 教程