Sorting Kotlin密封类-如何按密封类排序,类似于按枚举排序
在Java中,我们可以很容易地按枚举对集合进行排序,如下所示:Sorting Kotlin密封类-如何按密封类排序,类似于按枚举排序,sorting,kotlin,enums,Sorting,Kotlin,Enums,在Java中,我们可以很容易地按枚举对集合进行排序,如下所示: Collections.sort(toSortEnumList, new Comparator<theEnum>() { @Override public int compare(theEnum o1, theEnum o2) { return o1.ordinal().compareTo(o2.ordinal()); } }); 这张照片是: 美国、德国、中国、巴西 降序排列。
Collections.sort(toSortEnumList, new Comparator<theEnum>() {
@Override
public int compare(theEnum o1, theEnum o2) {
return o1.ordinal().compareTo(o2.ordinal());
}
});
这张照片是:
美国、德国、中国、巴西
降序排列。不是我想要的。我想按密封类顺序(如Java枚举中的序号)进行排序,如下所示:
Collections.sort(toSortEnumList, new Comparator<theEnum>() {
@Override
public int compare(theEnum o1, theEnum o2) {
return o1.ordinal().compareTo(o2.ordinal());
}
});
巴西、美国、德国、中国
我认为密封类应该比枚举更好,但如果我不能做到这一点,可能枚举有优势
更新:多亏罗兰的帮助,我找到了封存的班级名单。但现在我想按它分类:以下是我到目前为止得到的:
Collections.sort(toSortList, object : Comparator<GoodCountries> {
override fun compare(left: GoodCountries, right: GoodCountries): Int {
return Integer.compare(
GoodCountries::class.sealedSubclasses.indexOf(left),
GoodCountries::class.sealedSubclasses.indexOf(right)
)
}
})
Collections.sort(toSortList,对象:Comparator{
覆盖有趣的比较(左:GoodCountries,右:GoodCountries):Int{
返回整数。比较(
GoodCountries::class.sealedSubclass.indexOf(左),
GoodCountries::class.sealedSubclass.indexOf(右)
)
}
})
但是我在indexOf
中得到以下错误:
类型推断失败。类型参数T的值应该在输入类型(参数类型、接收器类型或预期类型)中提及。试着明确地指定它
您的问题的快速答案是在比较器中切换
x
和y
,即x::class.java.name.compareTo(y::class.java.name)
较长的答案是,对于您的用例,枚举可能更好。当某些子类看起来与其他子类不同时,密封类会发光,并且拥有多个实例是很有意义的。例如,带有子类
Success
和Error
的密封类结果
,其中Success
保存数据而Error
保存异常。假设您希望对所有国家都一视同仁,您的用例似乎更适合于传统的枚举。可能不完全符合您的要求,但可能是
虽然密封类似乎没有像您已经注意到的序号一样的东西,但是类本身(即GoodCountries::class.sealedsubclass
)上有一个。此外,似乎的顺序是定义的类之一,即此列表中的巴西
始终排在第一位,美国
第二位,等等。如果它们不是全部嵌套的,则顺序不同(即,如果一些在外部,则列在第一位)
但是:文档中没有说明此顺序是故意选择的。既不在家也不在家
关于在密封类顺序中对实体进行排序的问题,您可能希望使用以下内容:
val entityList = listOf(Germany(), China(), USA(), Brazil(), Germany())
entityList.sortedBy { // or use sortedWith(compareBy {
GoodCountries::class.sealedSubclasses.indexOf(it::class)
}.forEach(::println) // or toList...
或者类似于:
GoodCountries::class.sealedSubclasses
.asSequence()
.flatMap { klazzInOrder ->
entityList.asSequence().filter { it::class == klazzInOrder }
}
.forEach(::println)
GoodCountries::class.sealedSubclasses.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.simpleName })
.forEach(::println)
这两种方法可能都不是关于性能的最佳选择,但我想你已经明白了
我之前添加的排序示例(当我没有意识到您实际上想要对实体而不是类型进行排序时):
您甚至可能希望结合使用nullsLast
和CASE\u INSENSITIVE\u ORDER
(如果您没有处理密封类,则最有可能这样做),在这种情况下,您可以编写如下内容:
GoodCountries::class.sealedSubclasses
.asSequence()
.flatMap { klazzInOrder ->
entityList.asSequence().filter { it::class == klazzInOrder }
}
.forEach(::println)
GoodCountries::class.sealedSubclasses.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.simpleName })
.forEach(::println)
您可以给您的GoodCountries
一个order
属性,如下所示:
sealed class GoodCountries(val order: Int) {
class Brazil : GoodCountries(0)
class USA : GoodCountries(1)
class Germany : GoodCountries(2)
class China : GoodCountries(3)
}
这不是一个完美的解决方案,因为您必须手动枚举,但这样可以保证所需的顺序
这样做将大大简化比较代码:
val sorted = toSortList.sortedBy(GoodCountries::order)
println(sorted.map { it::class.simpleName })
输出:
[巴西、美国、德国、中国]
Edit:更新了一个很好的想法,这使得代码更加干净(在GoodCountries
的构造函数中具有order
属性,而不是将其作为一个抽象变量,由子类覆盖)。我想按照枚举的顺序而不是升序对列表进行排序。您建议的比较器如何做到这一点?它正在进行词汇分类。我要道歉。如果不能用密封类,请告诉我哦,我明白了。我不确定是否有任何方法可以在运行时获得该订单。如果您需要,请使用枚举。您能告诉我如何进行排序吗。感谢您的帮助,我找到了以下内容:GoodCountries::class.nestedClasses,但它按错误的顺序提供了类您使用的是哪个版本的Kotlin?由于1.3存在sealedsubclass
,您应该尝试使用它,而不是nestedClasses
。。示例实际上在答案中:GoodCountries::class.sealedsubclass
您可能需要kotlin reflect
-依赖项Sealed子类
在“现在可以帮我排序吗?”。我有以下内容,但它说它无法推断类型,indexOf用红色下划线:Collections.sort(toSortList,object:Comparator{override fun compare(left:GoodCountries,right:GoodCountries):Int{return Integer.compare(GoodCountries::class.sealedsubclass.indexOf(left),GoodCountries::class.sealedsubclass.indexOf(right))}})我更新了我的问题,这样你们就可以看到我做了什么far@j2emanue为什么要对GoodCountries
密封的子类进行排序?如果访问sealedsubclass
,则顺序是它们的声明*。。。但正如回答中所述,我不知道这是否是故意的。。。所以,把它和一粒盐放在一起。。。我不明白你的示例代码。。。如果您只想按基于字符串的顺序对其排序,您可能只想执行:GoodCountries::class.sealedsubclass.sortedBy{it.simpleName}
。。。但按照我对你的理解,你想要的是那份声明的顺序。。。答案基本上描述了这一点;-)或者,如果你不喜欢重写,你也可以这样做:(我个人的偏好是避免OOP,因为OOP不会增加任何明显的价值,因为它通常更容易混淆。在我的链接中,我们只是像使用密封特性一样使用密封类。)@Chrispher我只能同意。我更新了我的答案:)