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

Java中Comparator的comparing与thenComparingInt联合排序失效问题

问题根因

次级数字排序逻辑未生效的核心原因:第一比较器直接使用完整文件名字符串做字典序比较,在第一排序阶段就已经完成所有文件的定序,后续定义的次级比较器完全没有触发机会。
字符串字典序为逐字符对比规则:对比FileB_120.txt和FileB_60.txt时,两个字符串前6位均为FileB_,对比到第7位字符时,前者为1(ASCII码49)、后者为6(ASCII码54),字典序规则下1 < 6,因此第一比较器直接判定FileB_120.txt顺序优先于FileB_60.txt,根本不会执行后续的数字提取比较逻辑。
你观察到的大写字母开头文件整体排在小写开头文件前的现象,也符合字符串字典序规则:大写字母ASCII码范围为65-90,小写字母为97-122,因此大写开头的文件名会在第一阶段整体排在小写开头文件前,和你当前的实际输出完全吻合。

修复方案

将第一比较器的比较维度从「完整文件名」修改为「下划线前的文件名前缀」,确保第一阶段仅按前缀分组排序,前缀相同的文件才会触发第二阶段的数值排序,即可得到预期顺序。
修复后的实现代码:

String fileExtension = ".txt";
try (Stream<Path> paths = Files.walk(Paths.get(resourcesPath))) {
    // 第一排序维度:按下划线前的文件名前缀比较
    Comparator<Path> byFilePrefix = Comparator.comparing(p -> {
        String fileName = p.getFileName().toString();
        return fileName.substring(0, fileName.indexOf("_"));
    });
    // 第二排序维度:按下划线后的数字做数值比较
    Comparator<Path> byPrefixAndNum = byFilePrefix.thenComparingInt(p -> {
        String fileName = p.getFileName().toString();
        String numStr = fileName.split("_")[1].replace(fileExtension, "");
        return Integer.parseInt(numStr);
    });

    List<Path> fileList = paths
            .filter(p -> p.getFileName().toString().endsWith(fileExtension))
            .sorted(byPrefixAndNum)
            .collect(Collectors.toList());

    for (Path eachFilePath : fileList) {
        // 写入Excel的业务逻辑
    }
}
排序效果

执行修复后的代码,文件读取顺序完全匹配预期:

FileB_60.txt
FileB_90.txt
FileB_120.txt
fileA_60.txt
fileA_90.txt
fileA_120.txt

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:42:52