
本文介绍在java中对形如“1d”“23m”的字符串列表进行自定义排序的方法:先按末尾字母(如d/m/y)分组升序,再按前面的数字部分数值升序排列,确保结果如(1d, 2d, 12d, 4m, 23m, 1y, 2y)。
本文介绍在java中对形如“1d”“23m”的字符串列表进行自定义排序的方法:先按末尾字母(如d/m/y)分组升序,再按前面的数字部分数值升序排列,确保结果如(1d, 2d, 12d, 4m, 23m, 1y, 2y)。
要实现该排序逻辑,核心在于提取两个关键排序维度:
-
主排序键:字符串末尾的字母(即单位标识,如
'D','M','Y'),按字典序升序; -
次排序键:字符串开头至末尾前一位的数字子串(如
"1","23","4"),需解析为int后按数值升序。
使用 Java 8+ 的函数式 Comparator API 可以简洁、安全、可读地实现这一逻辑:
myList.sort(
Comparator.comparing((String s) -> s.charAt(s.length() - 1))
.thenComparingInt(s -> Integer.parseInt(s.substring(0, s.length() - 1)))
);✅ 说明:
-
comparing(...)提取末尾字符作为第一级排序依据(自动按char的 Unicode 值排序,与字母顺序一致); -
thenComparingInt(...)在单位相同时,将前缀数字部分(substring(0, length-1))转为整数比较,避免"12D"错排在"2D"之前(即规避字符串字典序陷阱); - 使用
thenComparingInt而非thenComparing+Integer::parseInt,可直接利用int比较提升性能且避免装箱开销。
⚠️ 注意事项:
- 此方案假设所有输入格式合法(即每个字符串至少 2 个字符,且末尾为字母、前面全为数字)。若存在非法输入(如
"D","12AB","abc"),Integer.parseInt(...)或charAt(...)会抛出异常。生产环境建议增加预校验或使用try-catch+ 默认值处理; - 若需支持大小写不敏感排序(如
"d"和"D"视为相同单位),可改用comparing(s -> Character.toUpperCase(s.charAt(s.length() - 1))); - 对于不可变列表(如
List.of(...)),请先转换为ArrayList再调用sort(),或使用Stream.sorted(...).collect(Collectors.toList())创建新列表。
该方法简洁、高效、符合函数式编程习惯,彻底替代了手动拆分、类型转换和冗长 if-else 判断的传统写法,是现代 Java 排序实践的推荐范式。

















