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 示例项目(示例链接,可根据实际项目替换)