Am I missing something, or does StringBuilder lack the same "replace all occurrences of a string A with string B" function that the normal String class does? The StringBuilder replace function isn't quite the same. Is there any way to this more efficiently without generating multiple Strings using the normal String class?
-
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html I don't know if I'm missing something, but that function doesn't seem to exist. – meteoritepanama Aug 12 '10 at 23:02
-
2`String.replaceAll` the thing with *regexs*? I wouldn't worry about the overhead of converting between `StringBuilder` and `String`. – Tom Hawtin - tackline Aug 12 '10 at 23:33
14 Answers
Well, you can write a loop:
public static void replaceAll(StringBuilder builder, String from, String to) {
int index = builder.indexOf(from);
while (index != -1) {
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
}
Note that in some cases it may be faster to use lastIndexOf
, working from the back. I suspect that's the case if you're replacing a long string with a short one - so when you get to the start, any replacements have less to copy. Anyway, this should give you a starting point.
-
1Note that in case if `from` and `to` have different length this solution would move buffer tail on each replace. This can be quite ineffective for long buffer with many replacement occurrences. Ron Romero's answer doesn't have this shortcoming but involves single regexp search. What would be faster depends on use case, I guess. – Vadzim Dec 06 '13 at 13:43
-
While-Loop is not required: `builder = builder.replace(builder.indexOf(from), builder.indexOf(from) + from.length(), to);` – Amitabha Roy Jan 17 '19 at 11:23
-
2@AmitabhaRoy: That will replace *one* occurrence, not *all* occurrences as stated in the question. – Jon Skeet Jan 17 '19 at 11:35
You could use Pattern/Matcher. From the Matcher javadocs:
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());

- 9,211
- 8
- 43
- 64
-
-
5
-
This works for "dog" but is insufficient in the _general_ case because the replacement string has special characters. If you intend to use back-references in the replacement values, then you need to escape all _other_ backslashes and `$`. If you don't need to reference the matched string at all, then you can just run the replacement text through `Matcher.quoteReplacement(...)`. So `m.appendReplacement(sb, Matcher.quoteReplacement(someText));` – AndrewF Mar 08 '18 at 01:17
@Adam: I think in your code snippet you should track the start position for m.find() because string replacement may change the offset after the last character matched.
public static void replaceAll(StringBuilder sb, Pattern pattern, String replacement) {
Matcher m = pattern.matcher(sb);
int start = 0;
while (m.find(start)) {
sb.replace(m.start(), m.end(), replacement);
start = m.start() + replacement.length();
}
}

- 169
- 1
- 3
Look at JavaDoc of replaceAll method of String class:
Replaces each substring of this string that matches the given regular expression with the given replacement. An invocation of this method of the form str.replaceAll(regex, repl) yields exactly the same result as the expression
java.util.regex.Pattern.compile(regex).matcher(str).replaceAll(repl)
As you can see you can use Pattern and Matcher to do that.

- 11,297
- 12
- 56
- 84
The class org.apache.commons.lang3.text.StrBuilder
in Apache Commons Lang allows replacements:
public StrBuilder replaceAll(String searchStr, String replaceStr)
* This does not receive a regular expression but a simple string.

- 41,222
- 15
- 102
- 148
-
2
-
1org.apache.commons.text.StringSubstitutor is a great library for this type of work that is not deprecated. But works on Strings not StringBuilder. – Ted Cahall Aug 03 '18 at 11:47
-
You can use org.apache.commons.text.TextStringBuilder in org.apache.commons.commons-text instead – ihebiheb Sep 30 '19 at 14:25
Even simple one is using the String ReplaceAll function itself. You can write it as
StringBuilder sb = new StringBuilder("Hi there, are you there?")
System.out.println(Pattern.compile("there").matcher(sb).replaceAll("niru"));

- 59
- 1
- 2
-
5The replaceAll method returns String. So it is going to generate an instance in the String pool. This is not an efficient approach when there are multiple different replacements to be made. – AbhishekB Aug 02 '19 at 06:06
Yes. It is very simple to use String.replaceAll()
method:
package com.test;
public class Replace {
public static void main(String[] args) {
String input = "Hello World";
input = input.replaceAll("o", "0");
System.out.println(input);
}
}
Output:
Hell0 W0rld
If you really want to use StringBuilder.replace(int start, int end, String str)
instead then here you go:
public static void main(String args[]) {
StringBuilder sb = new StringBuilder("This is a new StringBuilder");
System.out.println("Before: " + sb);
String from = "new";
String to = "replaced";
sb = sb.replace(sb.indexOf(from), sb.indexOf(from) + from.length(), to);
System.out.println("After: " + sb);
}
Output:
Before: This is a new StringBuilder
After: This is a replaced StringBuilder

- 769
- 5
- 8
-
6The question was about replaceAll in StringBuilder class not in String class. – das Keks Jun 29 '18 at 19:56
-
-
Though this works for a single occurrence, it doesn't work for two or more occurrences. – M. Al Jumaily May 15 '21 at 04:41
java.util.regex.Pattern.matcher(CharSequence s) can use a StringBuilder as an argument so you can find and replace each occurence of your pattern using start() and end() without calling builder.toString()

- 34,472
- 31
- 113
- 192
Use the following:
/**
* Utility method to replace the string from StringBuilder.
* @param sb the StringBuilder object.
* @param toReplace the String that should be replaced.
* @param replacement the String that has to be replaced by.
*
*/
public static void replaceString(StringBuilder sb,
String toReplace,
String replacement) {
int index = -1;
while ((index = sb.lastIndexOf(toReplace)) != -1) {
sb.replace(index, index + toReplace.length(), replacement);
}
}
-
2Doesn't this go into infinite loop if replacement contains toReplace ? – abhilash Dec 28 '20 at 13:06
Here is an in place replaceAll that will modify the passed in StringBuilder. I thought that I would post this as I was looking to do replaceAll with out creating a new String.
public static void replaceAll(StringBuilder sb, Pattern pattern, String replacement) {
Matcher m = pattern.matcher(sb);
while(m.find()) {
sb.replace(m.start(), m.end(), replacement);
}
}
I was shocked how simple the code to do this was (for some reason I thought changing the StringBuilder while using the matcher would throw of the group start/end but it does not).
This is probably faster than the other regex answers because the pattern is already compiled and your not creating a new String but I didn't do any benchmarking.

- 47,843
- 23
- 153
- 203
public static String replaceCharsNew(String replaceStr,Map<String,String> replaceStrMap){
StringBuilder replaceStrBuilder = new StringBuilder(replaceStr);
Set<String> keys=replaceStrMap.keySet();
for(String invalidChar:keys){
int index = -1;
while((index=replaceStrBuilder.indexOf(invalidChar,index)) !=-1){
replaceStrBuilder.replace(index,index+invalidChar.length(),replaceStrMap.get(invalidChar));
}
}
return replaceStrBuilder.toString();
}
-
You should really add some explanation as to why this code should work - you can also add comments in the code itself - in its current form, it does not provide any explanation which can help the rest of the community to understand what you did to solve/answer the question. – ishmaelMakitla Jun 15 '16 at 17:54
-
I had this following scenario that I need to replace multiple invalid chars with some chars . I just tweaked little bit of above code and wanted to post it @JUnitTest public void testReplaceCharsNew(){ Map
map = new HashMap – ramesh Jun 15 '16 at 18:09(); map.put(",", "/"); map.put(".",""); map.put(";","/"); String s = Utils.replaceCharsNew("test;Replace,Chars,New.",map); assertEquals("test/Replace/Chars/New",s); }
How about create a method and let String.replaceAll
do it for you:
public static void replaceAll(StringBuilder sb, String regex, String replacement)
{
String aux = sb.toString();
aux = aux.replaceAll(regex, replacement);
sb.setLength(0);
sb.append(aux);
}

- 7,062
- 9
- 53
- 79
I found this method: Matcher.replaceAll(String replacement); In java.util.regex.Matcher.java you can see more:
/**
* Replaces every subsequence of the input sequence that matches the
* pattern with the given replacement string.
*
* <p> This method first resets this matcher. It then scans the input
* sequence looking for matches of the pattern. Characters that are not
* part of any match are appended directly to the result string; each match
* is replaced in the result by the replacement string. The replacement
* string may contain references to captured subsequences as in the {@link
* #appendReplacement appendReplacement} method.
*
* <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
* the replacement string may cause the results to be different than if it
* were being treated as a literal replacement string. Dollar signs may be
* treated as references to captured subsequences as described above, and
* backslashes are used to escape literal characters in the replacement
* string.
*
* <p> Given the regular expression <tt>a*b</tt>, the input
* <tt>"aabfooaabfooabfoob"</tt>, and the replacement string
* <tt>"-"</tt>, an invocation of this method on a matcher for that
* expression would yield the string <tt>"-foo-foo-foo-"</tt>.
*
* <p> Invoking this method changes this matcher's state. If the matcher
* is to be used in further matching operations then it should first be
* reset. </p>
*
* @param replacement
* The replacement string
*
* @return The string constructed by replacing each matching subsequence
* by the replacement string, substituting captured subsequences
* as needed
*/
public String replaceAll(String replacement) {
reset();
StringBuffer buffer = new StringBuffer(input.length());
while (find()) {
appendReplacement(buffer, replacement);
}
return appendTail(buffer).toString();
}

- 378
- 4
- 11
Kotlin Method
fun replaceAllStringBuilder(
builder: java.lang.StringBuilder,
from: String,
to: String
) {
if (!builder.contains(from)||from.isNullOrEmpty()) return
var index = builder.indexOf(from)
while (index != -1) {
builder.replace(index, index + from.length, to)
index += to.length
index = builder.indexOf(from, index)
}
}

- 2,735
- 21
- 26