1. Overview
In this tutorial, weβre going to be looking at various means we can remove or replace part of a String in Java.
Weβll explore removing and/or replacing a substring using a String API, then using a StringBuilder API and finally using the StringUtils class of Apache Commons library.
As a bonus, weβll also look into some common String replacement problems, such as replacing an exact word and removing all characters until a specific one.
2. String API
One of the simplest and straightforward methods of replacing a substring is using the replace, replaceAll or replaceFirst of a String class.
The replace() method takes two arguments β target and replacement text:
String master = "Hello World Baeldung!";
String target = "Baeldung";
String replacement = "Java";
String processed = master.replace(target, replacement);
assertTrue(processed.contains(replacement));
assertFalse(processed.contains(target));
The above snippet will yield this output:
Hello World Java!
If a regular expression is required in choosing the target, then the replaceAll() or replaceFirst() should be the method of choice. As their name implies, replaceAll() will replace every matched occurrence, while the replaceFirst() will replace the first matched occurrence:
String master2 = "Welcome to Baeldung, Hello World Baeldung";
String regexTarget = "(Baeldung)$";
String processed2 = master2.replaceAll(regexTarget, replacement);
assertTrue(processed2.endsWith("Java"));
The value of processed2 will be:
Welcome to Baeldung, Hello World Java
Itβs because the regex supplied as regexTarget will only match the last occurrence of Baeldung. In all examples given above, we can use an empty replacement and itβll effectively remove a target from a master.
3. StringBuilder API
We can also manipulate text in Java using the StringBuilder class. The two methods here are delete() and replace().
We can construct an instance of a StringBuilder from an existing String and then use the methods mentioned to perform the String manipulation as desired:
String master = "Hello World Baeldung!";
String target = "Baeldung";
String replacement = "Java";
int startIndex = master.indexOf(target);
int stopIndex = startIndex + target.length();
StringBuilder builder = new StringBuilder(master);
Now we can remove the target with the delete():
builder.delete(startIndex, stopIndex);
assertFalse(builder.toString().contains(target));
We can as well use the replace() to update the master:
builder.replace(startIndex, stopIndex, replacement);
assertTrue(builder.toString().contains(replacement));
One apparent difference between using the StringBuilder and the String API is that weβve to get the start and the stop index of the target String ourselves.
4. StringUtils Class
Another method weβll consider is the Apache Commons library.
First, letβs add the required dependency to our project:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
The latest version of the library can be found here.
The StringUtils class has methods for replacing a substring of a String:
String master = "Hello World Baeldung!";
String target = "Baeldung";
String replacement = "Java";
String processed = StringUtils.replace(master, target, replacement);
assertTrue(processed.contains(replacement));
There is an overloaded variant of the replace() that takes an integer max parameter, which determines the number of occurrences to replace. We can also use the replaceIgnoreCase() if case-sensitivity is not a concern:
String master2 = "Hello World Baeldung!";
String target2 = "baeldung";
String processed2 = StringUtils.replaceIgnoreCase(master2, target2, replacement);
assertFalse(processed2.contains(target));
Next, letβs look at some common String replacement problems.
5. Replacing Exact Words
In this example, weβll learn how to replace an exact word inside a String.
The straightforward way to perform this replacement is using a regular expression with word boundaries.
The word boundary regular expression is \b. Enclosing the desired word inside this regular expression will only match exact occurrences.
First, letβs see how to use this regular expression with the String API:
String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!";
String regexTarget = "\\bcar\\b";
String exactWordReplaced = sentence.replaceAll(regexTarget, "truck");
The exactWordReplaced string contains:
"A truck is not the same as a carriage, and some planes can carry cars inside them!"
Only the exact word will be replaced. Notice backward slash always needs to be escaped when working with regular expressions in Java.
An alternate way to do this replacement is using the RegExUtils class from the Apache Commons Library, which can be added as a dependency as we saw in the previous section:
String regexTarget = "\\bcar\\b";
String exactWordReplaced = RegExUtils.replaceAll(sentence, regexTarget, "truck");
While both methods will yield the same result, deciding which one should be used will depend on our specific scenario.
6. Removing All Characters Until a Specific One
In real-world projects, we sometimes need to remove all characters until a specific character from a String input. An example can quickly explain the problem:
static final String INPUT1 = "some prefix=Important Info: a=b";
Letβs assume we have the above String input, and our task is to remove everything until the first equal (β=β) character. Therefore, our expected result is βImportant Info: a=bβ.
This is an βinclusiveβ scenario, as we remove the characters including the first equal character. Additionally, there is an βexclusiveβ scenario. Next, letβs see another example:
static final String INPUT2 = "some prefix<a, <b, c>>"
Given INPUT2, we aim to remove everything until the first β<β character exclusively. That is to say, we expect to see β<a, <b, c>>β as a result.
Next, letβs solve the problem using different methods. Of course, weβll discuss both inclusive and exclusive scenarios.
For simplicity, weβll skip the input validation part and assume the input always contain at least one β=β character.
6.1. Using indexOf() and substring()
The String.indexOf() method finds the first occurrence index of a String in another String. Also, the String.substring() method allows us to extract a substring from the input String by providing a beginIndex (inclusive) and optionally an endIndex (exclusive).
Next, letβs combine these to standard methods to solve the problem:
String result1 = INPUT1.substring(INPUT1.indexOf("=") + 1);
assertEquals("Important Info: a=b", result1);
As the code above shows, we initially used indexOf() to retrieve the index of the first β=β character in the input. Since we aim to remove the first β=β character as well, we applied β+ 1β to the index we obtained.
Subsequently, we passed this calculated index to substring() as the beginIndex argument. Itβs worth noting that as we didnβt specify the endIndex argument, substring() returns characters from beginIndex to the end of the input.
Itβs not a challenge to adjust the solution to make it work for the βexclusiveβ scenario. If we want to exclude the target character, we just donβt apply β + 1β to the indexOf() result:
String result2 = INPUT2.substring(INPUT2.indexOf("<"));
assertEquals("<a, <b, c>>", result2);
6.2. Using split()
Our input can be considered as two parts separated by an β=β character:
INPUT : "some prefix=Important Info: a=b"
Part1 : "some prefix"
Separator : '='
Part2 : Important Info: a=b"
Another idea to solve the problem is for us to split the input into two parts and take only the second part.
The split() method allows us to split an input String into multiple String values by providing a regex-based separator. Additionally, we can provide the limit argument to specify the desired number of elements in the resulting array. Since we aim to split the input into two parts, letβs pass 2 as the limit to split():
String result1 = INPUT1.split("=", 2)[1];
assertEquals("Important Info: a=b", result1);
If we intend to use split() to address the βexclusiveβ scenario, we must provide split() a zero-width assertion regex, such as a positive lookahead assertion:
String result2 = INPUT2.split("(?=<)", 2)[1];
assertEquals("<a, <b, c>>", result2);
The β(?=<)β pattern asserts that the current position in the input String is followed by the character β<β. However, it doesnβt include β<β in the overall match.
6.3. Using replaceFirst()
Weβve previously witnessed the effectiveness of regex-based replacement. This problem isnβt a challenge for regex-based replacement either.
We can use replaceFirst() to solve this problem. replaceFirst() works pretty similar to replaceAll(). The difference is, as its name tells, replaceFirst() applies the substitution on the match only once.
Some might consider using replaceFirst() with the regex pattern β.*=β. Letβs see if this approach helps us achieve the desired outcome:
String wrongResult = INPUT.replaceFirst(".*=", "");
assertEquals("b", wrongResult);
As the test above shows, after the replacement, we got βbβ as the result. This is because β*β is a greedy quantifier. Thus, β.*=β matches anything up until the last β=β character in the input. This greedy matching is also a common pitfall.
There are several ways to address the βgreedy matchingβ issue. One approach is to append a question mark after β.*β, to turn it into a non-greedy pattern:
String result1 = INPUT1.replaceFirst(".*?=", "");
assertEquals("Important Info: a=b", result1);
As a non-greedy pattern, β.*?=β matches anything until the first equal character.
Alternatively, we can use the negate operator (^) within a character class ([^=]) to match any character other than β=β:
result1 = INPUT1.replaceFirst("[^=]*=", "");
assertEquals("Important Info: a=b", result1);
Finally, letβs slightly adjust this solution to address the βexclusiveβ scenario:
String result2 = INPUT2.replaceFirst("[^<]*", "");
assertEquals("<a, <b, c>>", result2);
As demonstrated, by excluding the target character from the pattern, we successfully solved the problem.
7. Replacing the Last Occurrence of a Text
Sometimes, the input can contain the same text multiple times, but we only want to replace the last occurrence. Letβs say we have this String:
final static String INPUT3 = "The first word, the second word, the last word should be replaced.";
Now, we want to replace the last βwordβ with β*WORD*β to have the following result:
final static String EXPECTED3 = "The first word, the second word, the last *WORD* should be replaced.";
In this section, letβs explore two different ways to achieve this.
7.1. Reversing, Replacing, and Reversing Again
Weβve learned replaceFirst() replaces the first occurrence with a desired replacement. However, we aim to replace the last occurrence of the target pattern. Therefore, if we can somehow transform the last occurrence into the first occurrence, then we can use the replaceFirst() method to solve the problem.
Following this idea, we can reverse the input String to turn the last occurrence into the first one:
".decalper eb dluohs drow tsal eht ,drow dnoces eht ,drow tsrif ehT"
However, as we can see, after reversing the input, the target text gets reversed: βwordβ becomes βdrowβ
Therefore, we must reverse the target text and the replacement to call replaceFirst(). Of course, after calling replaceFirst(), we shouldnβt forget to reverse the result to get the expected result.
There are many ways to reverse a String in Java. Letβs create a method to use StringBuilder to perform the reverse operation:
String reverseString(String input) {
return new StringBuilder(input).reverse().toString();
}
Next, letβs implement the logic we discussed earlier:
String theWord = "word";
String replacement = "*WORD*";
String reversedInput = reverseString(INPUT3);
String reversedTheWord = reverseString(theWord);
String reversedReplacement = reverseString(replacement);
String reversedResult = reversedInput.replaceFirst(reversedTheWord, reversedReplacement);
String result = reverseString(reversedResult);
assertEquals(EXPECTED3, result);
As the test above shows, this approach does the job.
7.2. Using the lastIndexOf() Method
The βreverse-replace-reverseβ approach solves the problem. However, we have to reverse everything, such as the input, the target text, the replacement, and the result.
Alternatively, we can achieve our goal in a more straightforward way using the lastIndexOf() method from the standard library:
String theWord = "word";
String replacement = "*WORD*";
int index = INPUT3.lastIndexOf(theWord);
String result = INPUT3.substring(0, index) + replacement + INPUT3.substring(index + theWord.length());
assertEquals(EXPECTED3, result);
Finally, letβs walk through the code to understand how it works.
First, we find the last occurrence using lastIndexOf() to locate the position of the last occurrence of the target word. Then, we divide and concatenate, dividing the input into two parts (before and after the last occurrence), and then concatenating them with the replacement: before + replacement + after.
8. Conclusion
In conclusion, weβve explored multiple ways of removing and replacing a substring in Java. The best method to apply still largely depends on the current situation and context.
