如何根据/比较 Kotlin 中的多个值进行排序? [英] How to sort based on/compare multiple values in Kotlin?

查看:32
本文介绍了如何根据/比较 Kotlin 中的多个值进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 class Foo(val a: String, val b: Int, val c: Date) 并且我想对基于 Foo 的列表进行排序在所有三个属性上.我该怎么办?

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 的 stdlib 为此提供了许多有用的辅助方法.

Kotlin's stdlib offers a number of useful helper methods for this.

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

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() 辅助方法:

Second, you can let Foo implement Comparable<Foo> using the compareValuesBy() helper method:

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() 不带参数的扩展方法接收列表的排序副本:

Then you can call the sorted() extension method without parameters to receive a sorted copy of the list:

val sortedList = list.sorted()

排序方向

如果您需要对某些值进行升序排序并根据其他值进行降序排序,stdlib 还提供了相应的函数:

Sorting direction

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

性能注意事项

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

Performance considerations

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 所指出的,与多个选择器进行比较会为 vararg 调用实例化一个数组每次.你不能通过提取数组来优化它,因为它会在每次调用时被复制.另一方面,您可以做的是将逻辑提取到静态比较器实例中并重用它:

As noted by Paul Woitaschek in the comments, comparing with multiple selectors will instantiate an array for the vararg call everytime. You can't optimize this by extracting the array as it will be copied on every call. What you can do, on the other hand, is extract the logic into a static comparator instance and reuse it:

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 中的多个值进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆