Я не уверен, что правильно понял ваш вопрос. Может быть, это то, что вы ищете:
def things = [
[name: 'aaa', title: '222'],
[name: 'aaa', title: '333'],
[title: '222'],
[title: '111'],
[name: 'bbb', title: '111'],
[title: '333'],
[name: 'aaa', title: '111'],
]
things.sort { a, b ->
// Compare by name and then by title.
a.name <=> b.name ?: a.title <=> b.title
}
assert things == [
[title: '111'],
[title: '222'],
[title: '333'],
[name: 'aaa', title: '111'],
[name: 'aaa', title: '222'],
[name: 'aaa', title: '333'],
[name: 'bbb', title: '111'],
]
То, что происходит внутри этой, казалось бы, невинной функции сравнения, на самом деле является довольно сильной магией синтаксиса Groovy. Но за этим не так уж сложно следить.
Во-первых, метод sort
вызывается с двоичной функцией, которая действует как компаратор (т.е. принимает два аргумента, a и b, и возвращает -1, если a b и 0, если a == b).
Эта анонимная функция: { a, b -> a.name <=> b.name ?: a.title <=> b.title }
использует " оператор космического корабля " (<=>
... это человек из космического корабля!), Чтобы сначала сравнить a и b по именам.
Если имена равны (или оба равны нулю), то результат a.name <=> b.name
равен 0, что ложно оценивается в " Операторе Элвиса " (?:
... представить его как смайлик), значит, результат a.title <=> b.title
возвращается.
В противном случае, если результат сравнения имен не равен 0, тогда это верно оценивается в операторе Элвиса, и это значение возвращается.
Это все с учетом того, что вы можете сравнивать нулевые значения со строками и что 'any string' > null
всегда выполняется (то же самое, что сказать, что 'any string' <=> null == 1
).
Таким образом, окончательный результат состоит в том, что элементы без имени сначала сортируются по заголовку, а затем элементы с именем и заголовком упорядочиваются сначала по имени, а затем по заголовку.
Надеюсь, это было то, что вы искали. Если вы ожидали другого упорядочения отсортированных элементов, не стесняйтесь уточнить это в комментариях:)
Обновление
Существует также не очень документированный OrderBy
объект, который можно использовать в этом случае:
things.sort new OrderBy([{it.name}, {it.title}])