50

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.

Community
  • 1
  • 1
Soyuz
  • 1,077
  • 1
  • 8
  • 16

4 Answers4

119

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!

Tom
  • 15,798
  • 4
  • 37
  • 48
  • 3
    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? – Spencer Kormos Aug 13 '13 at 17:08
  • 2
    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? – ryvantage Dec 02 '13 at 18:49
  • 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! – Spencer Kormos Dec 03 '13 at 04:17
  • concatenating strings using + will be turned to Stringbuilder from the very biggining of java (http://web.archive.org/web/20041205170952/http://java.sun.com:80/docs/books/jls/first_edition/html/15.doc.html#40226) – ihebiheb Jan 22 '19 at 18:36
3

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.

jmoreno
  • 12,752
  • 4
  • 60
  • 91
  • 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. – Soyuz Feb 18 '13 at 00:23
2

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.

bssstudio
  • 174
  • 3
  • Rewrote the question. I am aware of what you said, I just mean, what should I actually write? – Soyuz Feb 18 '13 at 00:13
  • 1
    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. – Jeroen Vannevel Dec 25 '15 at 21:26
0

I might've misunderstood your question, but StringBuilder is faster when appending Strings. So, yes, if you are appending "hundreds-thousands of lines", you definitely should use StringBuilder (or StringBuffer if you are running a multithreaded app).

(More thorough answer in comments)

Soyuz
  • 1,077
  • 1
  • 8
  • 16
  • 1
    Apparently modern/mature Java compilers are smart enough to convert concatenation operations into StringBuilder append operations, so what's the point of using StringBuilder in code when it's less readable, and when String concats are converted into StringBuilder operations anyway? – Soyuz Feb 18 '13 at 00:10
  • 3
    Oh now I see your point, mate. Yes, you are right: the compiler will recognize a chance to optimize your code and will replace a regular String.concat by StringBuilder most of the times - but not always. You cannot rely on the compiler. If the code is complex, the compiler may well miss the opportunity of optimization. If I were you, I'd choose to make my code a little bit less readable for the sake of ensuring optimization. –  Feb 18 '13 at 00:14