Java Remove Extra Spaces Between Words in a String

Java remove extra spaces between words with replaceAll() and strip(), normalizeSpace(), split and join, plus non-breaking spaces and line breaks.

A string with runs of spaces and a tab collapsed to single spaces by strip() and replaceAll

To remove extra spaces between words in Java, we replace every run of whitespace with a single space using replaceAll(“\\s+”, ” “), and call strip() to remove the spaces at both ends. The result has one space between words, which is what we call normalized whitespace.

We normalize whitespace in user input before we store, compare or search it, for example in a search box, a full-name field or text pasted from a PDF or a web page, where tabs, line breaks and double spaces end up between the words.

The following example cleans up a String with uneven spaces in two ways.

String blogName = "  how to   do    in  java   .         com ";
String normalized = blogName.strip().replaceAll("\\s+", " ");   // "how to do in java . com"
String commons = StringUtils.normalizeSpace(blogName);          // "how to do in java . com"

Notice that both lines also remove the leading and trailing spaces. We look at the regex in detail, at normalizeSpace() from Apache Commons Lang, at two solutions without regex, at non-breaking spaces that \\s does not match, and at a variant that keeps line breaks.

1. Remove Extra Spaces Between Words with a Regular Expression

Using a regular expression to replace two or more whitespace characters with one space is the shortest solution, and it needs no library. The pattern \\s+ is written with two backslashes in Java source, because the backslash also escapes characters in a Java string literal.

  • The class \\s matches one whitespace character, which can be a space, a tab (\\t), a new line (\\n), a carriage return (\\r), a form feed (\\f) or a vertical tab (\\x0B).
  • The quantifier + means one or more occurrences, so a run of mixed spaces and tabs counts as one match.
A string with runs of spaces and a tab collapsed to single spaces by strip() and replaceAll
The strip() call removes the outer whitespace, and replaceAll(“\\s+”, ” “) turns each inner run into one space

Note that replaceAll() alone does not trim the string. A run of spaces at the start or at the end becomes one space that stays in the result, so we call strip() as well.

String blogName = "  how to   do    in  java   .         com ";
String noStrip = blogName.replaceAll("\\s+", " ");               // " how to do in java . com "
String tabs = "name:\t\tLokesh\n\nrole:  author".replaceAll("\\s+", " ");  // "name: Lokesh role: author"

The method String.replaceAll() compiles the regex on every call. When we normalize many strings, for example every row of a CSV import, we compile the Pattern once and reuse it.

final class SearchText {
    private static final Pattern WHITESPACE = Pattern.compile("\\s+");

    static String normalize(String query) {
        if (query == null) {
            return "";
        }
        return WHITESPACE.matcher(query.strip()).replaceAll(" ").toLowerCase(Locale.ROOT);
    }
}
String query = SearchText.normalize("  Spring   Boot\tTesting ");  // "spring boot testing"
String missing = SearchText.normalize(null);                        // ""

Say a book store logs every search term to find popular topics. Without normalization, “Spring Boot”, “spring boot” and ” Spring Boot” end up as three different terms in the report. After SearchText.normalize(), all three count as spring boot, and the same key also matches the cache entry for that search.

2. Using StringUtils.normalizeSpace() from Apache Commons Lang

If a project already uses Apache Commons Lang, StringUtils.normalizeSpace() does the same job in one readable call. It returns the argument with whitespace normalized in two steps.

  • It removes leading and trailing whitespace with trim().
  • It replaces each sequence of whitespace characters with a single space.
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.21.0</version>
</dependency>
String blogName = "how to   do    in  java   .         com";
String nameWithProperSpacing = StringUtils.normalizeSpace(blogName);  // "how to do in java . com"
String nothing = StringUtils.normalizeSpace(null);                    // null

The method returns null for null input, so it never throws. We do not add the dependency only for this method, because the regex version is one line long.

3. Removing Extra Spaces Without Regex

Two approaches avoid regular expressions. The first splits the text into words and joins them with one space, and the second walks over the characters with a StringBuilder. We leave out the old StringTokenizer approach, because StringTokenizer is a legacy class whose use is discouraged in new code.

3.1. Splitting and Joining the Words

The method split() with \\s+ returns the words without the whitespace between them, and String.join() puts them back together with one space. The strip() call before split() prevents an empty first word.

String blogName = "  how to   do    in  java   .         com ";
String joined = String.join(" ", blogName.strip().split("\\s+"));  // "how to do in java . com"
String emptyText = String.join(" ", "   ".strip().split("\\s+"));   // ""

The split-and-join version still uses a regex inside split(), but it reads well and gives us the words as an array, which helps when we want to count or reorder them as well, as in finding duplicate words in a string.

3.2. Collapsing Spaces in a Loop

Interviewers often ask for a solution without any regex or library. The collapseSpaces() method copies each non-whitespace character and writes one space only before a word that follows whitespace, so it trims and collapses in a single pass.

static String collapseSpaces(String text) {
    if (text == null) {
        return "";
    }
    StringBuilder out = new StringBuilder(text.length());
    boolean pendingSpace = false;
    for (int i = 0; i < text.length(); i++) {
        char c = text.charAt(i);
        if (Character.isWhitespace(c)) {
            pendingSpace = out.length() > 0;
        } else {
            if (pendingSpace) {
                out.append(' ');
                pendingSpace = false;
            }
            out.append(c);
        }
    }
    return out.toString();
}
String looped = collapseSpaces("  how to   do \t in  java  ");  // "how to do in java"
String blank = collapseSpaces(" \t\n ");                          // ""

4. Handling Non-Breaking and Unicode Spaces

Text copied from a web page or a word processor often contains the non-breaking space U+00A0, written &nbsp; in HTML. By default, \\s matches only the six ASCII whitespace characters, so a non-breaking space stays in the text and the words still look double-spaced.

String copied = "java\u00A0\u00A0streams \u2003 guide";
boolean nbspLeft = copied.replaceAll("\\s+", " ").contains("\u00A0");      // true
String unicodeAware = copied.replaceAll("(?U)\\s+", " ").strip();          // "java streams guide"
String commonsNbsp = StringUtils.normalizeSpace("java\u00A0\u00A0streams"); // "java  streams"

The flag (?U) turns on UNICODE_CHARACTER_CLASS, and with it \\s matches every character that Unicode marks as white space, including U+00A0 and the em space U+2003. The last line shows a quirk of normalizeSpace(), which turns each non-breaking space into a plain space but does not merge the two into one.

For text from browsers, PDFs or office documents, we use (?U)\\s+ instead of \\s+, because only the Unicode-aware pattern removes non-breaking spaces. The difference between trim() and strip() at the ends of a string is covered in removing leading and trailing whitespace.

5. Keeping Line Breaks While Removing Extra Spaces

The pattern \\s+ also replaces line breaks, which flattens an address or a multi-line comment into one line. To collapse only the spaces and tabs inside each line, we use \\h+, which matches horizontal whitespace, and clean up each line with lines().

String address = "  42   Main  Street\n   Springfield,\t IL ";
List<String> lines = address.lines()
        .map(line -> line.replaceAll("\\h+", " ").strip())
        .toList();                                     // [42 Main Street, Springfield, IL]
String cleaned = String.join("\n", lines);

The class \\h matches the space, the tab, the non-breaking space and the other Unicode space separators, but not \\n or \\r, so the two lines of the address stay separate.

6. Choosing a Method

All methods give the same result for plain ASCII text. They differ in dependencies, in how they treat non-breaking spaces and in whether they keep line breaks.

MethodTrims endsNon-breaking spaceKeeps line breaksNeeds a library
strip().replaceAll(“\\s+”, ” “)YesStaysNoNo
replaceAll(“(?U)\\s+”, ” “).strip()YesRemovedNoNo
replaceAll(“\\h+”, ” “) per lineWith strip()RemovedYesNo
String.join(” “, s.strip().split(“\\s+”))YesStaysNoNo
collapseSpaces() loopYesStaysNoNo
StringUtils.normalizeSpace()YesTurned into a space, not mergedNocommons-lang3

7. Remove Extra Spaces FAQs

Text pasted from other programs and the choice between trimming and collapsing lead to these questions.

7.1. How do we replace multiple spaces with a single space in Java?

We call text.strip().replaceAll(“\\s+”, ” “). The regex matches every run of whitespace, including tabs and new lines, and strip() removes the space that would remain at either end.

7.2. How do we remove all spaces from a string?

We replace the whitespace with an empty string, as in text.replaceAll(“\\s”, “”). That joins the words together, so we use it for values such as phone numbers or card numbers, not for sentences.

7.3. Why does replaceAll(“\\s+”, ” “) leave some double spaces?

The text contains non-breaking spaces (U+00A0), which \\s does not match by default. We use (?U)\\s+, or replace U+00A0 with a normal space first, as shown in section 4.

7.4. Should we use replaceAll() or a precompiled Pattern?

For a single call, replaceAll() is fine. In a loop over many strings, a static final Pattern avoids compiling the same regex again for every string.

8. Conclusion

The regex \\s+ with replaceAll(), combined with strip(), removes extra spaces between words in one line of plain Java. A precompiled Pattern helps when we normalize many strings, and StringUtils.normalizeSpace() is a readable choice in projects that already use Commons Lang.

For copied text, the Unicode-aware (?U)\\s+ also removes non-breaking spaces, and \\h+ keeps the line breaks when the layout of the text matters. The Java 11 strip() methods tutorial compares the trimming methods themselves.

9. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.