1. 简介
本文将探讨如何从数字字符串中移除无效零(包括前导零和尾随零)。我们将使用多种实现方式,包括标准Java核心库中的方法。每种实现都会处理正负数字符串的示例。
2. 使用 String.replaceAll()
首先看 String.replaceAll()
方法。该方法通过正则表达式替换字符串内容。我们将调用它来移除字符串中的前导零和尾随零。
核心思路:匹配字符串开头或结尾的所有零,并替换为空字符串。具体分两种情况:
- 如果字符串包含小数点 → 递归调用处理前导零和尾随零
- 否则 → 仅处理前导零
以小数为例:
@Test
public void givenPositiveNumberString_whenUsingStringReplaceAll_thenInsignificantZeroRemoved() {
String positiveNumber = "001200.35000";
positiveNumber = positiveNumber.contains(".") ? positiveNumber.replaceAll("^(-?)0+(\\d+)", "$1$2")
.replaceAll("0+$", "")
.replaceAll("\\.$", ".0") : positiveNumber.replaceAll("^(-?)0+(\\d+)", "$1$2");
assertEquals("1200.35", positiveNumber);
}
@Test
public void givenNegativeNumberString_whenUsingStringReplaceAll_thenInsignificantZeroRemoved() {
String negativeNumber = "-0015.052200";
negativeNumber = negativeNumber.contains(".") ? negativeNumber.replaceAll("^(-?)0+(\\d+)", "$1$2")
.replaceAll("0+$", "")
.replaceAll("\\.$", ".0") : negativeNumber.replaceAll("^(-?)0+(\\d+)", "$1$2");
assertEquals("-15.0522", negativeNumber);
}
✅ 正则解析:
^(-?)0+(\\d+)
→ 匹配前导零(保留负号)0+$
→ 匹配尾随零\\.$
→ 处理小数点后全为零的情况(替换为".0")
⚠️ 踩坑点:直接替换可能导致"123."变成"123",需特殊处理小数点后无数字的情况。
3. 使用 DecimalFormat
DecimalFormat
类允许通过模式自定义数字格式。但有个限制:它会根据模式截断小数位数。
@Test
public void givenPositiveNumberString_whenUsingDecimalFormat_thenInsignificantZeroRemoved() {
String positiveNumber = "001200.35000";
positiveNumber = new DecimalFormat("0.0#####").format(Double.valueOf(positiveNumber));
assertEquals("1200.35", positiveNumber);
}
@Test
public void givenNegativeNumberString_whenUsingDecimalFormat_thenInsignificantZeroRemoved() {
String negativeNumber = "-0015.052200";
negativeNumber = new DecimalFormat("0.0#####").format(Double.valueOf(negativeNumber));
assertEquals("-15.0522", negativeNumber);
}
✅ 模式解析:
"0.0####"
→0
:强制显示该位(即使为零)#
:仅当数字非零时显示- 五个
#
表示最多保留5位小数
❌ 局限性:
- 需预设最大小数位数
- 转换过程涉及
Double
,可能丢失精度(如超大数字)
4. 使用 BigDecimal
BigDecimal
提供了更专业的处理方式。初始化时自动移除前导零,并通过 stripTrailingZeros()
移除尾随零。注意:当小数部分全为零时,会直接省略小数点:
@Test
public void givenPositiveNumberString_whenUsingBigDecimal_thenInsignificantZeroRemoved() {
String positiveNumber = "001200.35000";
positiveNumber = new BigDecimal(positiveNumber).stripTrailingZeros()
.toPlainString();
assertEquals("1200.35", positiveNumber);
}
@Test
public void givenNegativeNumberString_whenUsingBigDecimal_thenInsignificantZeroRemoved() {
String negativeNumber = "-0015.052200";
negativeNumber = new BigDecimal(negativeNumber).stripTrailingZeros()
.toPlainString();
assertEquals("-15.0522", negativeNumber);
}
✅ 优势:
- 精确处理超大/超小数字
- 自动处理科学计数法问题
- 无需预设小数位数
⚠️ 特殊情况:
- 输入"123.000" → 输出"123"(小数点被移除)
- 输入"0.000" → 输出"0"
5. 总结
本文对比了三种移除无效零的方法:
方法 | 优点 | 缺点 |
---|---|---|
replaceAll() |
无需类型转换,纯字符串操作 | 正则复杂,边界情况处理繁琐 |
DecimalFormat |
代码简洁 | 精度丢失,需预设小数位数 |
BigDecimal |
精确可靠,自动处理各种情况 | 性能稍低(对象创建开销) |
💡 选择建议:
- 需要高性能且数字范围可控 →
DecimalFormat
- 处理金融/超大数字 →
BigDecimal
- 简单场景且不想引入额外依赖 →
replaceAll()