1. 简介

在本教程中,我们将介绍如何对包含字母和数字的字符串进行排序,排序依据是字符串中所包含的数字。

核心思路是:提取字符串中的数字部分,然后根据这些数字进行排序。

我们会处理一些常见边界情况,比如空字符串、无效数字等,并编写单元测试验证逻辑的正确性。

2. 问题描述

在开始编码前,我们先明确几个前提:

输入字符串可能包含以下几种形式:

  • 仅数字(如 "123")
  • 仅字母(如 "abc")
  • 字母数字混合(如 "a1b2c3")

数字类型包括:

  • 整数
  • 浮点数

处理规则:

  • 如果数字被字母隔开,我们应将字母去除,合并数字部分。例如:"2d3" → "23"
  • 如果字符串无效或无法解析为数字,则统一返回 0 作为默认值

3. 使用正则表达式实现提取数字

我们首先想到使用 正则表达式(Regex) 来提取字符串中的数字和小数点。

✅ 正则表达式说明:

String DIGIT_AND_DECIMAL_REGEX = "[^\\d.]";
  • [^\\d.]:表示匹配除了数字和小数点外的所有字符
  • replaceAll(...):将非数字和小数点的字符全部替换掉

✅ 示例代码:

String digitsOnly = input.replaceAll(DIGIT_AND_DECIMAL_REGEX, "");

✅ 处理空值与非法数字:

if ("".equals(digitsOnly)) return 0;

try {
    return Double.parseDouble(digitsOnly);
} catch (NumberFormatException nfe) {
    return 0;
}

✅ 构建比较器:

为了方便排序,我们构建一个 Comparator<String>,使用上面的方法提取数字后进行排序:

public static Comparator<String> createNaturalOrderRegexComparator() {
    return Comparator.comparingDouble(NaturalOrderComparators::parseStringToNumber);
}

4. 单元测试验证

写完逻辑之后,必须写测试来验证是否符合预期。

✅ 测试用例说明:

List<String> testStrings = Arrays.asList("a1", "d2.2", "b3", "d2.3.3d", "c4", "d2.f4");

testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());

List<String> expected = Arrays.asList("d2.3.3d", "a1", "d2.2", "d2.f4", "b3", "c4");

assertEquals(expected, testStrings);

✅ 测试覆盖的几种情况:

原始字符串 提取后的数字 备注
"a1" 1 简单提取
"d2.2" 2.2 浮点数
"d2.3.3d" 2.3.3 → 无效 返回 0
"d2.f4" 2.4 合并处理
"b3" 3 整数
"c4" 4 整数

⚠️ 注意:"d2.3.3d" 中包含多个小数点,无法解析为合法数字,因此按规则返回 0。

5. 总结

在本教程中,我们通过正则表达式提取字符串中的数字,并基于这些数字对字符串进行自然排序。

我们处理了以下常见问题:

  • 字符串中夹杂字母
  • 多个小数点导致无法解析
  • 空字符串或无效输入

最后,我们通过单元测试验证了各种边界情况,确保逻辑健壮。

如果你在实际开发中遇到类似需求,比如排序文件名、日志条目、版本号等,这个方法可以作为一个简单粗暴的解决方案。

完整代码可参考:GitHub 示例项目(示例链接,可根据实际项目替换)


原始标题:Sorting Strings by Contained Numbers in Java