Java: String concat vs StringBuilder - optimised, so what should I do?

41,742

Solution 1

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!

Solution 2

The key phrase in your question is "supposedly slower". You need to identify if this is indeed a bottleneck, and then see which is faster.

If you are about to write this code, but have not written it yet, then write whatever is clearer to you and then if necessay see if it is a bottleneck.

While it makes sense to use the code you consider more likey to be faster, if both are equally readable, actually taking time to find out which is faster when you don't have a need is a waste of time. Readability above performance until performance is unacceptable.

Solution 3

It depends on the case, but StringBuilder is thought to be a bit faster. If you are doing concatenation inside a loop then I would suggest you use StringBuilder.

Anyway, I would advise you to profile and benchmark your code (if you are doing such a massive append).

Be careful though: instances of StringBuilder are mutable and are not to be shared between threads (unless you really know what you are doing.) as opposed to String which are immutable.

Share:
41,742
Soyuz
Author by

Soyuz

Updated on May 03, 2020

Comments

  • Soyuz
    Soyuz about 4 years

    In this answer, it says (implies) that String concatenation is optimised into StringBuilder operations anyway, so when I write my code, is there any reason to write StringBuilder code in the source? Note that my use case is different from the OP's question, as I am concatenating/appending hundreds-thousands of lines.

    To make myself clearer: I am well-aware about the differences of each, it's just that I don't know if it's worth actually writing StringBuilder code because it's less readable and when its supposedly slower cousin, the String class, is converted automagically in the compilation process anyway.

  • Soyuz
    Soyuz about 11 years
    Rewrote the question. I am aware of what you said, I just mean, what should I actually write?
  • Soyuz
    Soyuz about 11 years
    Actually, after (just) rewriting the code both ways, there's little difference in readability since it's just changing the class declarations and turning concat() to append(). I guess I'll stick with StringBuilder to ensure performance then.
  • Spencer Kormos
    Spencer Kormos over 10 years
    Is your decompiled code (in the second for loop) the output of an actual decompilation, or is this your guess? If you debug a for/while loop with a "+" string concatenation in it, you'll find that the StringBuilder object is not recreated in every loop, but in fact the same one is reused. Otherwise, if you're substituting a heavier object (i.e. StringBuilder for String), what optimization are you truly getting?
  • ryvantage
    ryvantage over 10 years
    I'd like to know the answer to @SpencerKormos' question too. Does the compiler actually create a new StringBuilder for each loop iteration? Why would that be optimal?
  • Spencer Kormos
    Spencer Kormos over 10 years
    Rereading the answer, and the link in the OP's question, the point that Tom was making, was that if the concat operation is occurring in the loop, then there's no optimization by the compiler on the overall code block (which would include the for loop). In that case, you would declare your StringBuilder before the for loop, and use append() inside the loop, making the concat operation most efficient (i.e. the last code block from Tom). Hope that makes sense, and thanks for bringing me back to this!
  • Jeroen Vannevel
    Jeroen Vannevel over 8 years
    There really should be some sort of proof or source to back up "StringBuilder is thought to be a bit faster". I assume this is because of the lack of synchronization overhead but still -- sources would be nice.
  • ihebiheb
    ihebiheb over 5 years
    concatenating strings using + will be turned to Stringbuilder from the very biggining of java (web.archive.org/web/20041205170952/http://java.sun.com:80/d‌​ocs/…)