String Vs. Stringbuilder

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("", "") or StringBuilder.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



Leave a reply



Submit