我想在我的域类中实现默认排序顺序,并立即发现它不适用于getAll
方法。没什么大不了的,我只是使用了list
。问题是域类中的默认排序顺序不允许您指定多个排序字段(as seen here)。
我的目标是首先按照Foo
对象的名称,然后按照自己的名称对所有Bar
个对象进行排序。
class Foo {
String name
String Bar
}
class Bar {
String name
}
如何在域类中实现这一点,所以每次调用.list()
时都不必指定长/讨厌的比较器?
我的一次尝试:
static Comparator getComparator() {
def c = { a, b ->
def result = a.bar.name.compareTo( b.bar.name );
if ( result == 0 ) {
result = a.name.compareTo( b.name );
}
}
return c as Comparator
}
然后我可以打电话给Foo.list(Foo.getComparator())
...如果我能让它发挥作用。
更新
我认为我在这里非常接近,只是在同一种类型的闭包中实现两次比较时遇到了麻烦。
Foo.list().sort{ a, b ->
def result = a.bar.name <=> b.bar.name;
// Things mess up when I put this if statement in.
if( result == 0 ) {
a.name <=> b.name
}
}
迪斯科!
class Foo { // My domain class
// ...
static Comparator getComparator() {
def c =[
compare: { a, b ->
def result = a.bar.name <=> b.bar.name;
if( result == 0 ) {
result = a.name <=> b.name
}
return result
}
] as Comparator
}
// ...
}
在我的控制器中实现如下:
Foo.list().sort( Foo.getComparator() )
PS:
上述工作,但Jeff Storey在我的回答之后在他的回答中发布了一些代码,并且他的代码工作并且比我的好得多,所以使用它:)
答案 0 :(得分:4)
在您的情况下,让Foo
实施Comparable
是否有意义并且实施可以按照您的描述进行比较?然后,当您对列表中的对象进行排序时,因为它们是Comparable
,它们将正确排序。
如果你实现Comparable
没有意义,你需要指定一个比较器进行排序。
以下是基于您的评论的示例代码:
编辑:
class Person implements Comparable<Person> {
String firstName
String lastName
int compareTo(Person other) {
int lastNameCompare = lastName <=> other.lastName
return lastNameCompare != 0 ? lastNameCompare : firstName <=> other.firstName
}
String toString() {
"${lastName},${firstName}"
}
}
def people = [new Person(firstName:"John",lastName:"Smith"), new Person(firstName:"Bill",lastName:"Jones"), new Person(firstName:"Adam",lastName:"Smith")]
println "unsorted = ${people}"
println "sorted = ${people.sort()}"
打印:
unsorted = [Smith,John, Jones,Bill, Smith,Adam]
sorted = [Jones,Bill, Smith,Adam, Smith,John]
答案 1 :(得分:2)
为了进一步简化上面的帖子(我会评论它但我还没有代表),你可以使用elvis运算符链接groovy比较运算符:
class Person implements Comparable<Person> {
String firstName
String lastName
int compareTo(Person other) {
return lastName <=> other.lastName ?: firstName <=> other.firstName
}
String toString() {
"${lastName},${firstName}"
}
}
def people = [new Person(firstName:"John",lastName:"Smith"), new Person(firstName:"Bill",lastName:"Jones"), new Person(firstName:"Adam",lastName:"Smith")]
println "unsorted = ${people}"
println "sorted = ${people.sort()}"
这会给你相同的结果,因为在groovy的眼中0被认为是假的,这将使它看到链中的下一个条件。