Java 如何基于字符串首个出现的数字对字符串数组进行数值排序
自定义字符串排序实现方案
问题本质
Arrays.sort()默认对字符串的比较逻辑是逐字符匹配的字典序,对比"1."、"18."、"2."时,会先比较开头的单个字符,判定"1."和"18."的开头字符排序小于"2.",不会把开头的连续数字整体当成数值做大小判断,最终得到不符合预期的排序结果。
核心实现逻辑
自定义排序规则的核心是绕开默认逐字符比较,针对每个字符串提取目标排序权重:
- 定位每个字符串中第一个出现数字的位置
- 截取从该位置开始的所有连续数字字符,转换为数值类型
- 比较器直接基于提取出的数值做大小对比,完成排序
可直接使用的代码实现
import java.util.Arrays; import java.util.regex.Pattern; public class NumericSortDemo { // 预编译正则匹配首个连续数字段,减少重复编译的性能损耗 private static final Pattern FIRST_NUM_PATTERN = Pattern.compile("\\d+"); public static void main(String[] args) { String[] array = { "18.sdfahsdfkjadf", "1.skjfhadksfhad", "2.asldfalsdf" }; Arrays.sort(array, (s1, s2) -> { int num1 = extractFirstNumber(s1); int num2 = extractFirstNumber(s2); return Integer.compare(num1, num2); }); // 验证排序结果 Arrays.stream(array).forEach(System.out::println); } private static int extractFirstNumber(String str) { var matcher = FIRST_NUM_PATTERN.matcher(str); if (matcher.find()) { return Integer.parseInt(matcher.group()); } // 边界兜底:无数字的字符串统一排到队尾,可根据竞赛要求调整位置 return Integer.MAX_VALUE; } }
运行上述代码的输出结果完全符合预期:
1.skjfhadksfhad 2.asldfalsdf 18.sdfahsdfkjadf
场景适配优化
- 若竞赛数据集规模较大,正则匹配的性能不足以满足时间要求,可以替换手动遍历的数字提取逻辑:逐字符扫描字符串,碰到第一个数字后持续拼接后续连续数字字符直到碰到非数字字符,解析为数值即可,运行效率更高
- 若题目给出的字符串中首个数字段长度超过
int类型的取值范围,需要替换为Long或BigInteger类型解析数值,避免溢出导致比较错误 - 若题目要求首个数字段数值相等时,需按字符串原始字典序做次级排序,只需要在比较器中追加数值相等时的对比逻辑:
if (num1 == num2) return s1.compareTo(s2);
内容的提问来源于stack exchange,提问作者reedaccess_
相关产品推荐
相关产品推荐

