我有一种方法需要以多种可能的方式对集合进行排序。我没有多次调用myCollection.sortedBy
,而是希望将变量传递给sortedBy
的lambda,然后我将该变量传递给一个变量单次拨打sortedBy
。但是,我无法弄清楚lambda变量应具有的类型。请记住"排序字段"可能有不同的类型(但显然它们都是Comparable
。
这是我的问题的简化版本:
data class Person(val name: String, val age: Int)
enum class SortBy {
NAME, AGE
}
fun main(args: Array<String>) {
val people = listOf(Person("John", 30), Person("Mary", 20))
val sort = SortBy.NAME
val comparator = when (sort) {
SortBy.NAME -> { p: Person -> p.name }
SortBy.AGE -> { p: Person -> p.age }
}
// the line below won't compile
people.sortedBy(comparator).forEach(::println)
}
有什么想法吗?
答案 0 :(得分:7)
问题是两个lambda具有非常不同的类型,因此变量comparator
的类型简单地推断为Any
,这是第一个常见的超类型。如果你需要能够将lambdas中的任何一个赋值给它,那么这个变量就没有其他类型(Any?
除外)。
然后,根据您最终得到的结果((Person) -> Int
或(Person) -> String
),sortedBy
方法必须以某种方式推断其类型参数,这也是不可能的。处理这两种情况。
但是,有一个解决方案。您可以在不同的Comparator<Person>
分支中创建when
个实例,而不是通过compareBy
函数将Person
实例与之比较的特定类型包装起来:
val comparator: Comparator<Person> = when (sort) {
SortBy.NAME -> compareBy { it.name }
SortBy.AGE -> compareBy { it.age }
}
然后使用sortedWith
方法,该方法采用Comparator
而不是选择器lambda:
people.sortedWith(comparator).forEach(::println)
答案 1 :(得分:0)
您可以简单地使用属性引用
val people = listOf(Person("John", 30), Person("Mary", 20))
val sort = Person::age
people.sortedBy(sort).forEach(::println)