String vs. StringBuilder
Yes, the performance difference is significant. See the KB article "How to improve string concatenation performance in Visual C#".
I have always tried to code for clarity first, and then optimize for performance later. That's much easier than doing it the other way around! However, having seen the enormous performance difference in my applications between the two, I now think about it a little more carefully.
Luckily, it's relatively straightforward to run performance analysis on your code to see where you're spending the time, and then to modify it to use StringBuilder
where needed.
Difference between string and StringBuilder in C#
A string
instance is immutable. You cannot change it after it was created. Any operation that appears to change the string instead returns a new instance:
string foo = "Foo";
// returns a new string instance instead of changing the old one
string bar = foo.Replace('o', 'a');
string baz = foo + "bar"; // ditto here
Immutable objects have some nice properties, such as they can be used across threads without fearing synchronization problems or that you can simply hand out your private backing fields directly without fearing that someone changes objects they shouldn't be changing (see arrays or mutable lists, which often need to be copied before returning them if that's not desired). But when used carelessly they may create severe performance problems (as nearly anything – if you need an example from a language that prides itself on speed of execution then look at C's string manipulation functions).
When you need a mutable string, such as one you're contructing piece-wise or where you change lots of things, then you'll need a StringBuilder
which is a buffer of characters that can be changed. This has, for the most part, performance implications. If you want a mutable string and instead do it with a normal string
instance, then you'll end up with creating and destroying lots of objects unnecessarily, whereas a StringBuilder
instance itself will change, negating the need for many new objects.
Simple example: The following will make many programmers cringe with pain:
string s = string.Empty;
for (i = 0; i < 1000; i++) {
s += i.ToString() + " ";
}
You'll end up creating 2001 strings here, 2000 of which are thrown away. The same example using StringBuilder:
StringBuilder sb = new StringBuilder();
for (i = 0; i < 1000; i++) {
sb.Append(i);
sb.Append(' ');
}
This should place much less stress on the memory allocator :-)
It should be noted however, that the C# compiler is reasonably smart when it comes to strings. For example, the following line
string foo = "abc" + "def" + "efg" + "hij";
will be joined by the compiler, leaving only a single string at runtime. Similarly, lines such as
string foo = a + b + c + d + e + f;
will be rewritten to
string foo = string.Concat(a, b, c, d, e, f);
so you don't have to pay for five nonsensical concatenations which would be the naïve way of handling that. This won't save you in loops as above (unless the compiler unrolls the loop but I think only the JIT may actually do so and better don't bet on that).
StringBuilder vs String concatenation in toString() in Java
Version 1 is preferable because it is shorter and the compiler will in fact turn it into version 2 - no performance difference whatsoever.
More importantly given we have only 3
properties it might not make a
difference, but at what point do you
switch from concat to builder?
At the point where you're concatenating in a loop - that's usually when the compiler can't substitute StringBuilder
by itself.
String vs String builder. which is faster? If stringbuilder then why use string
The advantage of String
is that it is immutable: once constructed, the contents of a string instance cannot change anymore. This means that you pass strings by reference without making copies all the time.
For example, suppose you would pass a StringBuilder
to a class. Then you could change the contents of that StringBuilder
afterwards, and confuse the class. So the class would need to make a copy to make sure that the content doesn't change without it knowing about it. With a String
this is not necessary, because a String
is immutable.
Now, when you're in the process of building a string, this immutability is actually a problem, because a new String
instance must be created for every concatenation. That's why the StringBuilder
class exists: it is an auxiliary class which is intended to build strings (hence the name).
In practice, it's often not necessary to use a StringBuilder
explicitly. The Java compiler will automatically use a StringBuilder
for you when you write things like String result = "some constant" + a + b;
. Only with complex building logic (using if
and for
blocks, for example) you need to do that yourself.
List of Strings VS String Array VS Stringbuilder
ArrayList
is a good general purpose List
and will usually out-perform an Array
or LinkedList
. Here is the breakdown in terms of time complexity (V
is the type, i
is an index):
Type | add(V) | remove(V) | get(i) |
-------------------------------------------
Array | O(n) | O(n) | O(1) |
ArrayList | O(1) | O(n) | O(1) |
LinkedList | O(1) | O(1) | O(n) |
In general you can use this rule:
Array: Use if you know the exact number of elements and don't need to add or remove elements.
List: Use if you don't know the exact number of elements and need to add or remove elements.
StringBuilder
is completly different. StringBuilder
is a mutable String. You can think of it as List<Character>
. In that sense, it is probably not what you need so to compare it to List<String>
or String[]
is probably not benificial.
String vs. StringBuilder when editing a long string?
What is better
string.Replace("", "")
orStringBuilder.Replace("", "")
?
Neither. They both do nothing useful. In the more general case:
- if you're doing one replacement, the internal-call of
String.Replace
should be fine - if you're doing lots of replacements, consider
StringBuilder
to avoid intermediate strings
Performance between String.format and StringBuilder
After doing a little test with StringBuilder
vs String.format
I understood how much time it takes each of them to solve the concatenation. Here the snippet code and the results
Code:
String name = "stackover";
String lName = " flow";
String nick = " stackoverflow";
String email = "stackoverflow@email.com";
int phone = 123123123;
//for (int i = 0; i < 10; i++) {
long initialTime1 = System.currentTimeMillis();
String response = String.format(" - Contact {name=%s, lastName=%s, nickName=%s, email=%s, phone=%d}",
name, lName, nick, email, phone);
long finalTime1 = System.currentTimeMillis();
long totalTime1 = finalTime1 - initialTime1;
System.out.println(totalTime1 + response);
long initialTime2 = System.currentTimeMillis();
final StringBuilder sb = new StringBuilder(" - Contact {");
sb.append("name=").append(name)
.append(", lastName=").append(lName)
.append(", nickName=").append(nick)
.append(", email=").append(email)
.append(", phone=").append(phone)
.append('}');
String response2 = sb.toString();
long finalTime2 = System.currentTimeMillis();
long totalTime2 = finalTime2 - initialTime2;
System.out.println(totalTime2 + response2);
//}
After of run the code several times, I saw that String.format
takes more time:
String.format: 46: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 38: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 51: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
But if I run the same code inside a loop, the result change.
String.format: 43: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
The first time String.format
runs it takes more time, after of that the time is shorter even though it does not become constant as a result of StringBuilder
As @G.Fiedler said: "String.format
has to parse the format string..."
With these results it can be said that StringBuilder
is more efficient thanString.format
What is the difference bewteen the string and string builder in c#
StringBuilder
is mutable which gives better performance when you need to manipulate content multiple times.
In case of string
, it has to create instances multiple times because string is immutable.
Java: String concat vs StringBuilder - optimised, so what should I do?
I think the use of StringBuilder
vs +
really depends on the context you are using it in.
Generally using JDK 1.6 and above the compiler will automatically join strings together using StringBuilder
.
String one = "abc";
String two = "xyz";
String three = one + two;
This will compile String three
as:
String three = new StringBuilder().append(one).append(two).toString();
This is quite helpful and saves us some runtime. However this process is not always optimal. Take for example:
String out = "";
for( int i = 0; i < 10000 ; i++ ) {
out = out + i;
}
return out;
If we compile to bytecode and then decompile the bytecode generated we get something like:
String out = "";
for( int i = 0; i < 10000; i++ ) {
out = new StringBuilder().append(out).append(i).toString();
}
return out;
The compiler has optimised the inner loop but certainly has not made the best possible optimisations. To improve our code we could use:
StringBuilder out = new StringBuilder();
for( int i = 0 ; i < 10000; i++ ) {
out.append(i);
}
return out.toString();
Now this is more optimal than the compiler generated code, so there is definitely a need to write code using the StringBuilder
/StringBuffer
classes in cases where efficient code is needed. The current compilers are not great at dealing concatenating strings in loops, however this could change in the future.
You need to look carefully to see where you need to manually apply StringBuilder
and try to use it where it will not reduce readability of your code too.
Note: I compiled code using JDK 1.6, and and decompiled the code using the javap
program, which spits out byte code. It is fairly easy to interpret and is often a useful reference to look at when trying to optimise code. The compiler does change you code behind the scenes so it is always interesting to see what it does!
Related Topics
How to Get the Ip Address of the Server on Which My C# Application Is Running On
Splash Screen Waiting Until Thread Finishes
Mssql Error 'The Underlying Provider Failed on Open'
Wix Installer Msi Not Installing the Winform App Created With Visual Studio 2017
Get String Between Two Strings in a String
Could Not Establish Trust Relationship For Ssl/Tls Secure Channel - Soap
Detect If Deserialized Object Is Missing a Field With the Jsonconvert Class in Json.Net
Which .Net Dependency Injection Frameworks Are Worth Looking Into
Calculate the Number of Business Days Between Two Dates
Is There Any Significant Difference Between Using If/Else and Switch-Case in C#
How to Load Image to Wpf in Runtime
How to Apply an Xslt Stylesheet in C#
How to Generate a Stream from a String
.Net Process.Start Default Directory
How to Ensure That a Division of Integers Is Always Rounded Up