如何在Kotlin中按指定优先级的多属性对Data对象列表排序?
问题描述
现有如下Data类定义:
class Data(region: String, language: String, version: String)
以及该类的实例:
var data1 = Data("Spain", "En, Pl", "") var data2 = Data("Spain", "Ru, Es", "") var data3 = Data("France", "Fr, En", "v1.0") var data4 = Data("Germany", "", "v1.1")
(注:原代码存在重复定义data2的问题,已修正为data3和data4)
创建的列表为:
var list = mutableListOf(data1, data2, data3, data4)
需要按以下优先级从高到低对列表排序:
- 排序因子1(最高优先级):
region == "Spain"的元素排在最前;其次是region == "Europe";最后是region == "World";其他地区排在最后。 - 排序因子2:包含
"Es"的language属性优先于不包含的。 - 排序因子3:版本号更高的元素排在前面(如
v1.1优先于v1.0),版本号支持多位数字。
尝试了以下代码但结果错误:
list.sortedWith(compareBy({ it.region == "Spain"}, { it.language?.contains("Es") }, { it.version }))
请问如何正确实现这一排序逻辑?
正确实现方案
你的代码存在三个核心问题:
- 布尔值默认排序是
false在前、true在后,与需求的优先级方向相反; - 地区排序只判断了
Spain,未覆盖Europe和World的优先级规则; - 直接按字符串比较版本号会出现逻辑错误(比如
v1.10会被判定为小于v1.2)。
以下是修正后的完整代码:
// 定义地区优先级映射,数值越小优先级越高 val regionPriority = mapOf( "Spain" to 0, "Europe" to 1, "World" to 2 ) // 自定义版本号比较器:解析为数字数组后逐位比较 val versionComparator = Comparator<Data> { a, b -> fun parseVersion(versionStr: String): List<Int> { return versionStr.removePrefix("v") .split(".") .filter { it.isNotEmpty() } .mapNotNull { it.toIntOrNull() } } val verA = parseVersion(a.version) val verB = parseVersion(b.version) // 逐位对比版本号,长度不足的补0 for (i in 0 until maxOf(verA.size, verB.size)) { val numA = verA.getOrElse(i) { 0 } val numB = verB.getOrElse(i) { 0 } if (numA != numB) return@Comparator numB.compareTo(numA) // 降序排列,高版本在前 } 0 } // 组合多优先级排序规则 val sortedList = list.sortedWith( compareBy<Data> { // 不在映射中的地区默认最低优先级(数值3) regionPriority.getOrDefault(it.region, 3) }.thenByDescending { // 包含"Es"的元素优先,用降序让true排在前面 it.language.contains("Es") }.thenComparing(versionComparator) )
关键逻辑说明:
- 地区排序:通过映射表为目标地区分配优先级数值,确保
Spain→Europe→World→其他地区的顺序,逻辑清晰且易于扩展。 - 语言排序:使用
thenByDescending反转布尔值排序方向,让包含"Es"的元素排在前面。 - 版本号排序:将版本号解析为整数数组,逐位对比(长度不足补0),避免字符串比较的缺陷,同时实现高版本优先的降序排列。
内容的提问来源于stack exchange,提问作者NullPointerException
相关产品推荐
相关产品推荐

