Say I have a class Foo(val a: String, val b: Int, val c: Date)
and I want to sort a list of Foo
s based on all three properties. How would I go about this?
Say I have a class Foo(val a: String, val b: Int, val c: Date)
and I want to sort a list of Foo
s based on all three properties. How would I go about this?
Kotlin's stdlib offers a number of useful helper methods for this.
First, you can define a comparator using the compareBy()
method and pass it to the sortedWith()
extension method to receive a sorted copy of the list:
val list: List<Foo> = ...
val sortedList = list.sortedWith(compareBy({ it.a }, { it.b }, { it.c }))
其次,您可以让Foo
使用compareValuesBy()
helper方法实现Comparable<Foo>
:
class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> {
override fun compareTo(other: Foo)
= compareValuesBy(this, other, { it.a }, { it.b }, { it.c })
}
然后可以调用不带参数的sorted()
扩展方法来接收列表的排序副本:
val sortedList = list.sorted()
If you need to sort ascending on some values and descending on other values, the stdlib also offers functions for that:
list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c })
The vararg
version of compareValuesBy
is not inlined in the bytecode meaning anonymous classes will be generated for the lambdas. However, if the lambdas themselves don't capture state, singleton instances will be used instead of instantiating the lambdas everytime.
如注释中的Paul Woitaschek所示,与多个 Select 器进行比较将每次实例化vararg调用的array.您不能通过提取数组来优化这一点,因为它将在每次调用时被复制.另一方面,您可以做的是将逻辑提取到静电比较器实例中并重用它:
class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> {
override fun compareTo(other: Foo) = comparator.compare(this, other)
companion object {
// using the method reference syntax as an alternative to lambdas
val comparator = compareBy(Foo::a, Foo::b, Foo::c)
}
}