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

如何对包含Etape对象的列表按Etat与日期进行复合排序?

问题原因及解决方案

核心原因分析

你遇到的日期排序失效问题,大概率是两种排序场景的逻辑不一致导致的:

  • 单独按日期排序时,你可能**将String类型的date解析为了日期对象(比如LocalDate、Date)**进行比较,利用日期的自然时序排序;
  • 而使用sortedWith(compareBy(...))组合排序时,直接用了String类型的date做字典序比较——当日期字符串格式不是ISO标准格式(如yyyy-MM-dd)时,字典序和实际日期时序会出现偏差,看起来就像是日期排序失效。

还有一种小概率情况:如果Etat枚举的compareTo逻辑被重写过,导致同Etat的元素被错误判定为不相等,但你提到单独按Etat排序正常,这种可能性较低。

正确的组合排序写法

解决问题的核心是:组合排序时,对date字段使用日期对象而非字符串进行比较。以下是Java/Kotlin的正确示例:

Kotlin 示例

// 先按Etat枚举的ordinal排序(Valide(0)在前),再按解析后的LocalDate排序
val sortedList = etapeList.sortedWith(
    compareBy<Etape>(
        { it.etat }, // 第一排序键:Etat枚举,默认按ordinal比较
        { LocalDate.parse(it.echeancier.date) } // 第二排序键:解析为LocalDate后比较
    )
)

如果日期字符串不是ISO格式,需要指定格式化器:

val dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
val sortedList = etapeList.sortedWith(
    compareBy<Etape>(
        { it.etat },
        { LocalDate.parse(it.echeancier.date, dateFormatter) }
    )
)

Java 示例

// 使用Comparator.comparing组合排序
List<Etape> sortedList = etapeList.stream()
    .sorted(Comparator.comparing(Etape::getEtat) // 第一排序键:Etat枚举
        .thenComparing(etape -> LocalDate.parse(etape.getEcheancier().getDate()))) // 第二排序键:解析为LocalDate
    .collect(Collectors.toList());

非ISO格式日期的处理:

DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
List<Etape> sortedList = etapeList.stream()
    .sorted(Comparator.comparing(Etape::getEtat)
        .thenComparing(etape -> LocalDate.parse(etape.getEcheancier().getDate(), dateFormatter)))
    .collect(Collectors.toList());

验证点

  • 确认日期字符串格式,确保解析时不会抛出异常;
  • 可以在比较器中添加日志,验证同Etat的元素是否触发了日期比较逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:23:02