Say I have a class Foo(val a: String, val b: Int, val c: Date) and I want to sort a list of Foos 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)
    }
}

Kotlin相关问答推荐

我如何测试一个可组合组件没有显示,但如果它不存在也接受?

Kotlin多平台(KMP)保存到文件不能在iOS上保存

相当于roomdb中的DateTime Bigint列的是什么

如果带注释的成员未被特定块包围,则发出 IDE 警告

Kotlin:使用另一个列表和字母顺序对列表进行排序的有效方法

gradle 如何 Select 以-jvm结尾的库?

如何使用 Android CameraX 自动对焦

无法在 kotlin android 中以编程方式禁用 EditText

Kotlin 顶级函数与对象函数

如何在 kotlin 的片段类中更改 ActionBar 标题?

将 @Component.Builder 与构造函数参数一起使用

为什么 Kotlin Pair 中的条目不可变?

Kotlin-通过与属性列表进行比较来筛选对象列表

Android 与 Kotlin - 如何使用 HttpUrlConnection

Kotlin:如何修改成对的值?

如何获取Kotlin中变量的名称?

Kotlin 中更好的回调方法是什么?侦听器与高阶函数

Kotlin Flow 收集后无法执行代码

从 Kotlin 访问 Integer.class

Kotlin - 为什么我会得到 KotlinNullPointerException