1. 概述

本文将探讨从字符串中移除数字的多种实现方案。我们将从正则表达式入手,演示如何利用String类的replaceAll()方法和Pattern/Matcher类,并介绍Apache Commons Lang库的解决方案。此外,我们还会分析使用循环和StringBuilder的纯手动实现,以及基于Character流的现代处理方式。

核心思路:通过正则表达式\d匹配所有数字字符(0-9),将其替换为空字符串即可实现移除效果。为保持代码可读性,我们预先定义常量:

static final String INPUT_STRING = "M3a9n2y n8u6m7b5e4r0s1";
static final String EXPECTED_STRING = "Many numbers";
static final String DIGIT_REGEX = "\\d";

2. 使用正则表达式

正则表达式(regex)提供了强大的文本处理能力。Java的java.util.regex包支持通过\d模式匹配数字,实现高效简洁的字符串操作。

2.1. 使用String.replaceAll()

String类的replaceAll()方法可直接通过正则表达式替换匹配内容。简单粗暴的解决方案:

@Test
void whenUsingReplaceAll_thenGetExpectedResult() {
    String updatedString = INPUT_STRING.replaceAll(DIGIT_REGEX, "");

    assertEquals(EXPECTED_STRING, updatedString);
}

✅ 优点:代码简洁,一行搞定
❌ 缺点:每次调用都会重新编译正则表达式,性能稍逊

2.2. 使用Pattern和Matcher

PatternMatcher类提供更灵活的正则操作API。预编译模式可提升性能:

@Test
void whenUsingPatternAndMatcher_thenGetExpectedResult() {
    Pattern pattern = Pattern.compile(DIGIT_REGEX);
    Matcher matcher = pattern.matcher(INPUT_STRING);
    String updatedString = matcher.replaceAll("");

    assertEquals(EXPECTED_STRING, updatedString);
}

⚠️ 适用场景:需要多次使用同一正则表达式时,预编译能避免重复开销

2.3. 使用Apache Commons Lang

Apache Commons Lang库的RegExUtils类简化了正则操作。首先添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

一行代码实现数字移除:

@Test
void whenUsingApacheCommonsLang_thenGetExpectedResult() {
    String updatedString = RegExUtils.replacePattern(INPUT_STRING, DIGIT_REGEX, "");

    assertEquals(EXPECTED_STRING, updatedString);
}

✅ 优势:代码更简洁,底层已优化正则处理

3. 使用循环和StringBuilder

通过for循环遍历字符,配合StringBuilder构建结果字符串。手动控制每个字符的处理逻辑:

@Test
void whenUsingForLoop_thenGetExpectedResult() {
    StringBuilder sb = new StringBuilder();
    for (char ch : INPUT_STRING.toCharArray()) {
        if (!Character.isDigit(ch)) {
            sb.append(ch);
        }
    }

    assertEquals(EXPECTED_STRING, sb.toString());
}

✅ 优点:

  • 无需正则表达式依赖
  • 细粒度控制处理逻辑
  • 内存效率高(StringBuilder优化)

❌ 缺点:代码量相对较多

4. 使用Character流

Java 8的Stream API提供函数式处理方式。链式调用实现数字过滤:

@Test
void whenUsingCharacterStream_thenGetExpectedResult() {
    String updatedString = INPUT_STRING.chars()
      .filter(c -> !Character.isDigit(c))
      .mapToObj(c -> (char) c)
      .map(String::valueOf)
      .collect(Collectors.joining());

    assertEquals(EXPECTED_STRING, updatedString);
}

⚠️ 关键步骤解析:

  1. chars():获取字符流(IntStream)
  2. filter():过滤掉数字字符
  3. mapToObj():转换回char类型
  4. collect():拼接成最终字符串

✅ 优势:代码优雅,符合函数式编程风格
❌ 缺点:性能略低于循环方式(流操作开销)

5. 总结

本文对比了四种从字符串中移除数字的方案:

方法 适用场景 优势 劣势
replaceAll() 简单场景,单次操作 代码极简 重复编译正则表达式
Pattern/Matcher 高频正则操作 预编译提升性能 代码稍复杂
Apache Commons Lang 已引入该库的项目 API简洁,底层优化 需额外依赖
循环+StringBuilder 无正则依赖/需精细控制 高性能,无额外开销 代码量较多
Character流 函数式编程风格 链式调用优雅 性能略逊

选择建议

  • 优先使用replaceAll()(简单场景)或Pattern/Matcher(高频场景)
  • 已用Apache Commons的项目直接调用RegExUtils
  • 追求极致性能时选循环+StringBuilder
  • 函数式爱好者可尝试流式处理

完整代码示例见GitHub仓库


原始标题:How to Remove Digits From a String | Baeldung