Why is StringBuilder
much faster than string concatenation using the +
operator? Even though that the +
operator internally is implemented using either StringBuffer
or StringBuilder
.
public void shortConcatenation(){
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime <= 1000){
character += "Y";
}
System.out.println("short: " + character.length());
}
//// using String builder
public void shortConcatenation2(){
long startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
while (System.currentTimeMillis() - startTime <= 1000){
sb.append("Y");
}
System.out.println("string builder short: " + sb.length());
}
I know that there are a lot of similar questions posted here, but these don't really answer my question.
Using StringBuilder resulted in a time ~6000 times faster than regular String 's.
StringBuilder is speedy and consumes less memory than a string while performing concatenations. This is because string is immutable in Java, and concatenation of two string objects involves creating a new object.
Yes, StringBuilder gives better performance while performing repeated operation over a string. It is because all the changes are made to a single instance so it can save a lot of time instead of creating a new instance like String .
StringBuffer is a mutable and synchronized. StringBuilder is also mutable but its not synchronized. Additionally StringBuffer locks Threads for access this thread safe data that's why operation goes slowly. StringBuilder does not lock thread and it runs in Multi Threading way that's why is fast.
Strings in Java are immutable. This means that methods that operate on strings cannot ever change the value of a string. String concatenation using += works by allocating memory for an entirely new string that is the concatenation of the two previous ones, and replacing the reference with this new string. Each new concatenation requires the construction of an entirely new String object.
In contrast, the StringBuilder and StringBuffer classes are implemented as a mutable sequence of characters. This means that as you append new Strings or characters onto a StringBuilder, it simply updates its internal array to reflect the changes you've made. This means that new memory is only allocated when the string grows past the buffer already existing in a StringBuilder.
Do you understand how it works internally?
Every time you do stringA += stringB;
a new string is created an assigned to stringA, so it will consume memory (a new string instance!) and time (copy the old string + new characters of the other string).
StringBuilder
will use an array of characters internally and when you use the .append()
method it will do several things:
System.arraycopy
to copy the characters of the string in the array.Personally, I think the allocation of a new string every time (creating a new instance of string, put the string, etc.) could be very expensive in terms of memory and speed (in while/for, etc. especially).
In your example, use a StringBuilder
is better, but if you need (example) something simple like a .toString()
,
public String toString() {
return StringA + " - " + StringB;
}
makes no differences (well, in this case it is better you avoid StringBuilder overhead which is useless here).
I can list a very nice example for understanding the same (I mean I felt it's a nice example). Check the code here taken from a LeetCode problem: https://leetcode.com/problems/remove-outermost-parentheses/
1: Using String
public String removeOuterParentheses(String S) {
String a = "";
int num = 0;
for(int i=0; i < S.length()-1; i++) {
if(S.charAt(i) == '(' && num++ > 0) {
a += "(";
}
if(S.charAt(i) == ')' && num-- > 1) {
a += ")";
}
}
return a;
}
And now, using StringBuilder.
public String removeOuterParentheses(String S) {
StringBuilder sb = new StringBuilder();
int a = 0;
for(char ch : S.toCharArray()) {
if(ch == '(' && a++ > 0) sb.append('(');
if(ch == ')' && a-- > 1) sb.append(')');
}
return sb.toString();
}
The performance of both varies by a huge margin. The first submission uses String while the latter one uses StringBuilder.
As explained above the theory is the same. String by property is immutable and synchronous,i.e. its state cannot be changed. The second, for example, is expensive owing to the creation of a new memory allocation whenever a concatenation function or "+" is used. It will consume a lot of heap and in return be slower. In comparison StringBuilder is mutable, it will only append and not create an overload on the memory consumed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With