When to use StringBuilder in Java [duplicate]
Asked Answered
H

9

398

It is supposed to be generally preferable to use a StringBuilder for string concatenation in Java. Is this always the case?

What I mean is this: Is the overhead of creating a StringBuilder object, calling the append() method and finally toString() already smaller then concatenating existing strings with the + operator for two strings, or is it only advisable for more (than two) strings?

If there is such a threshold, what does it depend on (perhaps the string length, but in which way)?

And finally, would you trade the readability and conciseness of the + concatenation for the performance of the StringBuilder in smaller cases like two, three or four strings?

Explicit use of StringBuilder for regular concatenations is being mentioned as obsolete at obsolete Java optimization tips as well as at Java urban myths.

Humility answered 10/1, 2011 at 8:52 Comment(1)
See this blog post for a detailed explanation:rationaljava.com/2015/02/the-optimum-method-to-concatenate.htmlConsciencestricken
H
561

If you use String concatenation in a loop, something like this,

String s = "";
for (int i = 0; i < 100; i++) {
    s += ", " + i;
}

then you should use a StringBuilder (not StringBuffer) instead of a String, because it is much faster and consumes less memory.

If you have a single statement,

String s = "1, " + "2, " + "3, " + "4, " ...;

then you can use Strings, because the compiler will use StringBuilder automatically.

Holiness answered 10/1, 2011 at 9:10 Comment(16)
Actually, nowadays I really would almost never use anything else than Strings. I used to advocate for these, but with advances of the JVM it's almost NEVER necessary anymore, fortunately. If you have a look at the bytecode for the above (at least with a JDK > 1.6u22), you will notice that everything is replaced by a StringBuilder. It's not only single statements anymore, but actually fairly complicated constructs. I just did several test cases on real-life code, and I actually don't find any situation where it doesn't use StringBuilders internally. Quite nice.Carissacarita
@haylem: Are you shure? - I have checked it with version 1.6.0.21, and of course the String loop use a String Builder to, but only to concatinate (s += ", " + i;) - so it creates a new String Builder for each loop! - so it is much slower, than using one StringBuilder which is created once out side of the loop and within the loop only its append method is invoked.Holiness
@haylem: have you proved your thesis?Holiness
@Ralph: I'll try to remember to send this out on Monday. I had different test cases with generated bytecode.Carissacarita
@Ralph: actually I just tried on a 1.6.0_18 and 1.6.0_24 on my machine it does indeed generate a StringBuilder per loop. Either I had created a very specific test scenario that was favorable at my office, or I was wrong. But it most cases I guess it would still not matter that much to me anymore, at it's not a significant performance in most situations (except the case of fairly long tight loops and to build fairly big strings, for instance maybe for generating documentation, XML data, or templating purposes). Normal use cases would just just too much boilerplate. But you were right above.Carissacarita
@Ralph: sorry, had a busy week, but I finally got around to dig that up, and as mentioned, I was indeed wrong. It does create a StringBuilder for each loop turn. Bummer. I could see situations where it's better that way, but I think they could detect some cases where they could implement an enhanced path detection. So there's still room for improvement there :). Thanks for having me verify that.Carissacarita
Great Ralph! Can you also add a link to the reference?Breskin
What's wrong with s.concat(", ").concat(i)?Funny
ViniciusPires: this question is about performance, s.concat(", ").concat(i) create the same result, but it also create a 2 new String objects for each loop iteration, that makes it slowerHoliness
Still @Carissacarita is right, I've wrote a sample performance benchmark that proves his claim blog.loxal.net/2014/11/… Of course, simplistic and so on... but still the difference is very clear :)Bendy
@Alexander Orlov: look at the byte codeHoliness
@Holiness Have you checked this with jdk 1.8? I am also curious about how you looked into the byte code and see it create a string builder for each loop.Mercantile
@qed: I haven't checked again for version of Oracle's javac for 1.8 or previews of 1.9 yet. If you want to give it a shot, you can simply use the javap tool for this, and look at the instructions. It's easy to figure out for a simple test case. I had saved one a while back, if I find it I'll report here but (as my lack of activity on SE site lately shows), my time is very limited.Carissacarita
@Mercantile - I used standard eclipse without any additional plugin: - I compiled an example progamm, and move only the class file to an new project and opend the classfile there - then eclipse was showing the byte code. -- I have not done this with jdk 1.8 but I am pretty sure, that it is still the same -- so nobody is preventing you from testing it with java 8Holiness
I tested with jdk 1.8.0 - it is the same byte code. Also I was a bit sceptic about big performance increase as object allocation is so cheap now. HOWEVER switching to explicit StringBuilder 1 instance gave me 0-1ms from ~120ms on 1000 iterations. So StringBuilder is still necessary for critical places in similar cases.Intended
Real life example, I had to modify a 10 MB HTML document in memory and send it to the client. I built a table of the changes to the string and built the result using a StringBuilder since I had many complex changes to make. The speedup over naive String + String was huge, the final result could process the HTML in under 10 seconds. The table of changes would have thousands to tens of thousands of changes to make so the overhead of creating and destroying so many automatic StringBuilder objects was huge.Gersham
S
54

Ralph's answer is fabulous. I would rather use StringBuilder class to build/decorate the String because the usage of it is more look like Builder pattern.

public String decorateTheString(String orgStr){
            StringBuilder builder = new StringBuilder();
            builder.append(orgStr);
            builder.deleteCharAt(orgStr.length()-1);
            builder.insert(0,builder.hashCode());
            return builder.toString();
}

It can be use as a helper/builder to build the String, not the String itself.

Swore answered 10/1, 2011 at 9:42 Comment(3)
I dont think StringBuilder has any relation to Builder Pattern. Name-match is by coincidence AFAIK.Slipnoose
Why are you mixing builder pattern with string builder? I guess you are trying to explain coding best practices.Fresh
Why was this answer upvoted even once? The proposed example makes a bad use of the StringBuilder (size not preallocated although known, insert makes array copies). In what is this better than the + operator? Doesn't answer the OPStagy
S
45

As a general rule, always use the more readable code and only refactor if performance is an issue. In this specific case, most recent JDK's will actually optimize the code into the StringBuilder version in any case.

You usually only really need to do it manually if you are doing string concatenation in a loop or in some complex code that the compiler can't easily optimize.

Spheroidicity answered 10/1, 2011 at 9:4 Comment(0)
C
7

Have a look at: http://www.javaspecialists.eu/archive/Issue068.html and http://www.javaspecialists.eu/archive/Issue105.html

Do the same tests in your environment and check if newer JDK or your Java implementation do some type of string operation better with String or better with StringBuilder.

Cassandry answered 10/1, 2011 at 8:59 Comment(0)
S
5

For two strings concat is faster, in other cases StringBuilder is a better choice, see my explanation in concatenation operator (+) vs concat()

Summitry answered 6/12, 2012 at 9:18 Comment(0)
E
5

Some compilers may not replace any string concatenations with StringBuilder equivalents. Be sure to consider which compilers your source will use before relying on compile time optimizations.

Estivation answered 12/2, 2013 at 16:17 Comment(2)
Interesting, I wasnt aware of that. Could you provide a reference to which compilers do replace the concatenation and which dont?Humility
No, I don't have that information. I'm just saying be careful relying on compile time optimizations. If you're positive all compilers you need provide certain optimization, great! If not, it might be better to assume they don't. But most importantly, only optimize what needs optimization.Estivation
D
4

The + operator uses public String concat(String str) internally. This method copies the characters of the two strings, so it has memory requirements and runtime complexity proportional to the length of the two strings. StringBuilder works more efficent.

However I have read here that the concatination code using the + operater is changed to StringBuilder on post Java 4 compilers. So this might not be an issue at all. (Though I would really check this statement if I depend on it in my code!)

Dillingham answered 10/1, 2011 at 9:10 Comment(0)
O
3

The problem with String concatenation is that it leads to copying of the String object with all the associated cost. StringBuilder is not threadsafe and is therefore faster than StringBuffer, which used to be the preferred choice before Java 5. As a rule of thumb, you should not do String concatenation in a loop, which will be called often. I guess doing a few concatenations here and there will not hurt you as long as you are not talking about hundreds and this of course depends on your performance requirements. If you are doing real time stuff, you should be very careful.

Odum answered 10/1, 2011 at 9:6 Comment(0)
L
2

The Microsoft certification material addresses this same question. In the .NET world, the overhead for the StringBuilder object makes a simple concatenation of 2 String objects more efficient. I would assume a similar answer for Java strings.

Lookout answered 10/1, 2011 at 8:57 Comment(3)
I guess the performance impact is mitigated by compiler optimizations similar to java, or do the certification materials imply an effective difference?Humility
The material explicitly states that in the case of 1 or 2 concatenations (2 or 3 strings, respectively), using the StringBuilder is the less efficient implementation.Lookout
seems to be different from java, then. Thank you anywayHumility

© 2022 - 2024 — McMap. All rights reserved.