1. Overview

In this tutorial, we’ll explore various methods to remove digits from Strings.

We’ll start with regular expressions, demonstrating how to utilize the replaceAll() method of the String class and how to employ Pattern and Matcher classes. We’ll also cover how Apache Commons Lang library can handle this task. Beyond regular expressions, we’ll examine a more manual approach using loops and StringBuilder. Finally, we will delve into using Character Streams for this purpose.

2. Using Regular Expressions

Regular expressions, or regex, provide a powerful and flexible way to search, match, and manipulate text. The java.util.regex package supports regular expressions. Regex offers an efficient and concise solution for removing digits from Strings.

To remove digits from a String, we need a regex pattern that identifies digits. In regex, \d matches any digit (0-9). By using \d, we can target all the digits in a String and replace them with an empty String.

To maintain clean and readable code, we’ll use constants for common values like the input String, the regex pattern, and the expected result:

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

Let’s start with the regex approach.

2.1. Using String‘s replaceAll()

*The replaceAll() method of the String class allows for replacing parts of a String that match a given regex pattern. By providing a regex pattern to replaceAll(), we can efficiently modify the String according to our needs:*

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

    assertEquals(EXPECTED_STRING, updatedString);
}

This example demonstrates how simple it is to use the replaceAll() method with a regex pattern to manipulate Strings.

2.2. Using Pattern and Matcher

The Pattern and Matcher classes from the java.util.regex package provides an advanced and flexible API for working with regular expressions.

By using these classes, we can compile a regex pattern using a Pattern and apply it to a String using a Matcher, which can then be used to perform various operations, such as finding, replacing, or splitting text:

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

    assertEquals(EXPECTED_STRING, updatedString);
}

The previous example illustrates the power of using the Pattern and Matcher classes for regex operations. By understanding how to compile and apply regex patterns with these classes, we can perform more complex and precise String manipulations.

2.3. Using Apache Commons Lang

Apache Commons Lang provides a library of utility classes for the java.lang package, enhancing core Java functionality. One of the classes, RegexUtils, offers useful methods for regular expression manipulation.

To use Apache Commons Lang, we add the commons-lang3 dependency in our pom.xml file:

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

To remove digits from a String using Apache Commons Lang, we can utilize the RegexUtils class combined with a regex pattern:

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

    assertEquals(EXPECTED_STRING, updatedString);
}

When we use Apache Commons Lang, we simplify manipulating Strings with minimal code.

3. Using Loop and StringBuilder

Using a for loop with a StringBuilder provides a straightforward approach to removing digits from a String. This method involves iterating over each Character in the String, checking if it’s a digit, and then appending non-digit Characters to a 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());
}

The previous code illustrates a simple and effective way to manipulate Strings using basic looping constructs. We gain fine-grained control over the String processing logic by manually iterating and appending Characters.

4. Using Character Streams

Stream provides a modern and concise way to process collections and sequences of data. We can efficiently filter and manipulate Characters in a String using Character Streams. In this example, we use a Stream to remove all digits from a String:

@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);
}

The previous code demonstrates the elegance of using Stream API to create a clean and efficient solution to our problem.

5. Conclusion

In this article, we explored multiple methods to remove digits from Strings, including using regular expressions with replaceAll() and the Pattern and Matcher classes, leveraging Stream API for a modern approach, and employing a traditional for loop with StringBuilder for clarity and simplicity. Each method offers unique strengths, from the powerful flexibility of regex to the functional style of Streams and the straightforward nature of loops, providing versatile solutions for String manipulation.

As always, the source code is available over on GitHub.