You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中Store列表多字段动态排序问题求助

门店列表排序问题解决方案

问题现状

开发Android门店列表应用时,按用户选择的多SortTag排序出现以下问题:

  • 整数类型字段仅按字符串首字符排序(如10排在2前面)
  • Double类型字段排序逻辑异常
  • 多标签排序时,后续标签会覆盖前面的排序结果,未实现优先级链式排序

错误原因分析

  1. 多标签排序逻辑错误:当前代码遍历selectedTags时,每次都基于原列表重新排序,而非在前一次排序结果基础上进行二次排序,导致仅最后一个标签生效。
  2. Comparator类型处理缺陷:
    • 数值类型判断后未执行return,最终执行字符串比较逻辑,整数被当作字符串排序
    • Double类型使用abs(valueFirst-valueSecond)丢失正负信息,无法正确反映升/降序
    • Float类型直接返回减法结果(Float转Int会丢失精度,不符合compare方法返回Int的规范)

修复后的完整代码

1. 修复多标签排序函数

使用fold链式组合多个Comparator,实现优先级排序(先按第一个标签排,相同则按第二个,以此类推):

fun sortListByAdditionalTags(
    list: MutableList<Store>,
    selectedTags: List<SortTag>
): MutableList<Store> {
    // 初始Comparator:按名称兜底排序
    val baseComparator = Comparator<Store> { o1, o2 ->
        o1.name.compareTo(o2.name)
    }
    
    // 链式组合所有选中的排序规则
    val finalComparator = selectedTags.fold(baseComparator) { acc, sortTag ->
        acc.thenComparing(AdditionalSortComparator(sortTag.key, sortTag.isAscending))
    }
    
    return list.sortedWith(finalComparator).toMutableList()
}

2. 修复自定义Comparator

修正数值类型比较逻辑,确保每个类型分支正确返回Int结果,避免字符串比较兜底:

class AdditionalSortComparator(
    private val sortProperty: String?,
    private val isAscending: Boolean
) : Comparator<Store> {
    // 提前缓存反射属性,避免每次compare都查找
    private val sortingDataProperty = Store::class.declaredMemberProperties.first { it.name == "sortingData" }
    private val targetProperty = sortProperty?.let {
        SortingData::class.declaredMemberProperties.firstOrNull { prop -> prop.name == it }
    }

    override fun compare(o1: Store?, o2: Store?): Int {
        if (o1 == null || o2 == null) return 0
        
        val s1 = sortingDataProperty.get(o1) as SortingData
        val s2 = sortingDataProperty.get(o2) as SortingData
        
        targetProperty?.let { prop ->
            val value1 = prop.get(s1)
            val value2 = prop.get(s2)
            
            return when (value1) {
                is Int -> compareValues(value1, value2) * if (isAscending) 1 else -1
                is Float -> value1.compareTo(value2) * if (isAscending) 1 else -1
                is Double -> value1.compareTo(value2) * if (isAscending) 1 else -1
                else -> compareValues(value1.toString(), value2.toString()) * if (isAscending) 1 else -1
            }
        }
        
        // 无匹配属性时按名称排序
        return o1.name.compareTo(o2.name) * if (isAscending) 1 else -1
    }
}

3. 性能优化方案(可选)

为避免反射带来的性能开销,可预定义属性映射替代反射:

// 预定义SortingData属性的获取函数
private val sortingPropertyMap = mapOf(
    "averageProductPrice" to { s: SortingData -> s.averageProductPrice as Comparable<Any> },
    "bestMatch" to { s: SortingData -> s.bestMatch as Comparable<Any> },
    "deliveryCosts" to { s: SortingData -> s.deliveryCosts as Comparable<Any> },
    "distance" to { s: SortingData -> s.distance as Comparable<Any> },
    "minCost" to { s: SortingData -> s.minCost as Comparable<Any> },
    "newest" to { s: SortingData -> s.newest as Comparable<Any> },
    "popularity" to { s: SortingData -> s.popularity as Comparable<Any> },
    "ratingAverage" to { s: SortingData -> s.ratingAverage as Comparable<Any> }
)

// 修改Comparator使用预定义映射
class AdditionalSortComparator(
    private val sortProperty: String?,
    private val isAscending: Boolean
) : Comparator<Store> {
    override fun compare(o1: Store?, o2: Store?): Int {
        if (o1 == null || o2 == null) return 0
        
        val propertyGetter = sortingPropertyMap[sortProperty] ?: return o1.name.compareTo(o2.name) * if (isAscending) 1 else -1
        
        val value1 = propertyGetter(o1.sortingData)
        val value2 = propertyGetter(o2.sortingData)
        
        return value1.compareTo(value2) * if (isAscending) 1 else -1
    }
}

关键修复点说明

  • 链式排序:通过fold和thenComparing实现多优先级排序,前一个标签排序结果相同时,才会使用下一个标签排序
  • 数值类型正确比较:使用compareValues(针对Int)和compareTo(针对Float/Double)获取正确的Int比较结果,避免字符串兜底
  • 方向控制:通过乘以1或-1统一处理升/降序逻辑,简化代码
  • 性能优化:预缓存反射属性或使用预定义映射,减少反射调用的性能损耗

内容的提问来源于stack exchange,提问作者Nayab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:24:27