如何基于/比较Kotlin中的多个值进行排序?

假设我有一个class Foo(val a: String, val b: Int, val c: Date) ,我想根据这三个属性对Foo列表进行排序。 我将如何去做这件事?

Kotlin的stdlib为此提供了许多有用的帮助方法。

首先,您可以使用compareBy()方法定义一个比较器,并将其传递给sortedWith()扩展方法,以接收列表的已排序副本:

 val list: List<Foo> = ... val sortedList = list.sortedWith(compareBy({ it.a }, { it.b }, { it.c })) 

其次,你可以让Foo使用compareValuesBy()辅助方法来实现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() 

排序方向

如果您需要对某些值进行升序排序并在其他值上递减,则stdlib还会提供以下功能:

 list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c }) 

性能考虑

compareValuesBy版本没有在字节码中内联,这意味着匿名类将被生成为lambda表达式。 但是,如果lambda本身不捕获状态,则将使用singleton实例,而不是每次都实例化lambda表达式。

正如Paul Woitaschek在评论中指出的,与多个选择器相比,每次都会为可变参数调用实例化一个数组。 您不能通过提取数组来优化它,因为它将在每次调用时被复制。 另一方面,您可以执行的操作是将逻辑提取到静态比较器实例中并重用:

 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) } } 
    Interesting Posts