String, StringBuffer, StringBuilder. What were they thinking? What are we thinking?

Nowadays both StringBuffer and Builder are sort of useless (from performance point of view). I explain why.

Nowadays both StringBuffer and Builder are sort of useless (from performance point of view). I explain why: StringBuilder was supposed to be faster than StringBuffer but any sane JVM can optimize away the synchronization. So it was quite a huge miss (and small hit) when it was introduced.

StringBuffer used NOT to copy the char when creating the String (in non shared variant); however that was a major source of issues, incl leaking huge char for small Strings. In 1.5 they decided that a copy of the char must occur every time and that practically made StringBuffer useless (the sync was there to ensure no thread games can trick out the String). That conserves memory, though and ultimately helps the GC (beside the obviously reduced footprint), usually the char is the top3 of the objects consuming memory.String.

Concat was and still is the fastest way to concatenate 2 strings (and 2 only... or possibly 3). Keep that in mind, it does not perform an extra copy of the char. Back to the useless part, now any 3rd party code can achieve the same performance as StringBuilder.

Even in java1.1 I used to have a class name AsycnStringBuffer which did exactly the same what StringBuilder does now, but still it allocates larger char than StringBuilder. Both StrinBuffer/StringBuilder are optimized for small Strings by default you can see the c-tor StringBuilder(String str) { super(str.length() + 16); append(str); } Thus if the 2nd string is longer than 16chars, it gets another copy of the underlying char. Pretty uncool.

That can be a side effect of attempt at fitting both StringBuilder/Buffer and the char into the same cache line (on x86) on 32bit OS... but I don't know for sure. As for the remark of hours of debugging, etc. Use your judgment, I personally do not recall ever having any issues w/ strings operations, aside impl. Rope alike structure for the sql generator of JDO impl.

Edit: Below I illustrate what java designers didn't do to make String operations faster. Please, note that the class is intended for java. Lang package and it can put there only by adding it to the bootstrap classpath.

However, even if not put there (the difference is a single line of code! ), it'd be still faster than StringBuilder, shocking? The class would have made string1+string2+... a lot better than using StringBuilder, but well... package java.

Lang; public class FastConcat { public static String concat(String s1, String s2){ s1=String. ValueOf(s1);//null checks s2=String. ValueOf(s2); return s1.

Concat(s2); } public static String concat(String s1, String s2, String s3){ s1=String. ValueOf(s1);//null checks s2=String. ValueOf(s2); s3=String.

ValueOf(s3); int len = s1.length()+s2.length()+s3.length(); char c = new charlen; int idx=0; idx = copy(s1, c, idx); idx = copy(s2, c, idx); idx = copy(s3, c, idx); return newString(c); } public static String concat(String s1, String s2, String s3, String s4){ s1=String. ValueOf(s1);//null checks s2=String. ValueOf(s2); s3=String.

ValueOf(s3); s4=String. ValueOf(s4); int len = s1.length()+s2.length()+s3.length()+s4.length(); char c = new charlen; int idx=0; idx = copy(s1, c, idx); idx = copy(s2, c, idx); idx = copy(s3, c, idx); idx = copy(s4, c, idx); return newString(c); } private static int copy(String s, char c, int idx){ s. GetChars(c, idx); return idx+s.length(); } private static String newString(char c){ return new String(0, c.

Length, c); //return String. CopyValueOf(c);//if not in java. Lang } }.

I'm shocked. Great answer. I'll read it carefully.

Thanks – santiagobasulto Mar 26 at 16:11 A few things: 1. The JVM can (AFAIK) only optimise out synchronisation for local variables (escape analysis) so when using nonlocal variables, StringBuilder will still be faster than StringBuffer. 2.

Using StringBuilder documents the fact that you’re not caring about synchronisation. When used right, this makes code easier to understand. 3.

Your posting makes it sound as if StringBuilder is never faster than concatenation. Your concat code is all fine but it solves a different problem than a StringBuilder. I doubt that it will be faster in a tight loop with a lot of concats.

– Konrad Rudolph Mar 28 at 8:57 1). Not really - it depends how much the JVM inlines,i.e. How much the object can possibly escape, also uncontended sync is close to free as well, nowadays (it does not inflate the object header).2) That's not really a performance concern (I myself tend to look at the code, mostly).

And 3) the posting doesn't say so, the sample code is provided to be used in case where you get>. String s="xxx: "+someInt+" yyy"+anotherString; That would beat any StringBuilder whatsoever... back to the point. A lot of impl.By java1.5 have dropped StringBuffer because it didn't help for shared (more than 1) calls.

– bestsss Mar 28 at 11:25 @Konrad, what, perhaps, is unclear: as of now, both StringBuilder/Buffer take zero benefits of being put in java. Lang package. Thus, a custom impl.

Form java1.1 performs as quick as StringBuilder. Before java1.5 StringBuffer used to try and play smart not to copy the char to avoid the allocation (and some minor GC) costs. That's ok, however not adding a few simple concat methods (like the snipped above) was not a smart move.

String. Concat was and is always faster than StringBuilder/Buffer for 2 strings. You can't even come closer (unless the JVM can use intrisics) – bestsss Mar 28 at 11:38.

StringBuffer was in Java 1.0; it was not any kind of a reaction to slowness or immutability. It's also not in any way faster or better than string concatenation; in fact, the Java compiler compiles String s1 = s2 + s3; into something like String s1 = new StringBuilder(s2). Append(s3).toString(); If you don't believe me, try it yourself with a disassembler (javap -c, for example.) The thing about "StringBuffer is faster than concatenation" refers to repeated concatenation.

In that case explicitly creating yoir own StringBuffer and using it repeatedly performs better than letting the compiler create many of them. StringBuilder was introduced in Java 5 for performance reasons, as you say. The reason it makes sense is that StringBuffer/Builder are virtually never shared outside of the method that creates them: 99% of their usage is something like the above, where they're created, used to append a few strings together, then discarded.

You're right Ernest. They are both from 1.0. I was just trying to make a point.

I've benchmarked String concatenation (with the + operator) vs StringBuffer.append() and is really faster. – santiagobasulto Mar 26 at 15:23 1 After the introduction of StringBuilder they changed the compiler to use StringBuilder instead of StringBuffer for implementing the + operator. – PaÅ­lo Ebermann Mar 26 at 16:22 @Paulo: indeed, that was a major part of the motivation!Fixed.

– Ernest Friedman-ll Mar 26 at 16:30.

Just a comment about your "StringBuilders and threads" remark: even in multi-threaded programs, it's very rare to want to build up a string across multiple threads. Typically, each thread will have some set of data and create a string from that, often by concatenating multiple strings together. They'll then convert that StringBuilder to a string, and that string can be safely shared among threads.

I don't think I've ever seen a bug due to a StringBuilder being shared between threads. Personally I wish StringBuffer didn't exist - it was in the "let's synchronize everything" phase of Java, leading to Vector and Hashtable which have been almost obsoleted by the unsynchronized ArrayList and HashMap classes from Java 2. It just took a little while long for the unsynchronized equivalent of StringBuffer to arrive.So basically: Use string when you don't want to perform manipulations, and want to be sure nothing else will Use StringBuilder to perform manipulation, usually over a short period Avoid StringBuffer unless you really, really need it - and as I say, I can't remember ever seeing a situation where I'd use StringBuffer instead of StringBuilder, when both are available.

Great Jon! Thanks! That was I was looking for.

I've been coding an aplication that has this little problem (several threads sharing a simple String) but is ONE weird and uncommon example. Great comparision with the collections! I've never thought about it.

You made a point. – santiagobasulto Mar 26 at 15:37 the biggest complaint I have with StringBuffer vs. StringBuilder is they are not related thru some interface, or abstract superclass. – MeBigFatGuy Mar 26 at 15:44 @MeBigFatGuy, use Appendable and CharSequence?

– bestsss Mar 26 at 15:55 @santiagobasulto: Sharing a string is fine - but sharing a StringBuilder/StringBuffer is the uncommon situation. – Jon Skeet Mar 26 at 16:01 @Jon, yes jon, that was what I meant. Several threads get the same instance of a StringBuffer and work with it.

– santiagobasulto Mar 26 at 16:07.

Decided to put the options to the test with a simple composition of XML exercise. Testing done on a 2.7GHz i5 with 16Gb DDR3 RAM for those wishing to replicate results. Code: private int testcount = 1000; private int elementCount = 50000; public void testStringBuilder() { long total = 0; int counter = 0; while (counter++ \n"); buffer.

Append(""); for (int I =0; I "); } buffer. Append(""); //System.out. Println(buffer.toString()); output = buffer.toString(); long end = System.nanoTime(); return end - start; } public void testStringBuffer(){ long total = 0; int counter = 0; while (counter++ \n"); buffer.

Append(""); for (int I =0; I "); } buffer. Append(""); //System.out. Println(buffer.toString()); output = buffer.toString(); long end = System.nanoTime(); return end - start; } Results: On OSX machine: StringBuilder build & output duration= 1047.000000 µs StringBuffer build & output duration= 1844.000000 µs On Win7 machine: StringBuilder build & output duration= 1869.000000 µs StringBuffer build & output duration= 2122.000000 µs So looks like performance enhancement might be platform specific, dependant on how JVM implements synchronisation.

References: Use of System.nanoTime() has been covered here -> Is System.nanoTime() completely useless? And here -> How do I time a method's execution in Java?. Source for StringBuilder & StringBuffer here -> http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java.lang.htm Good overview of synchronising here -> http://www.javaworld.com/javaworld/jw-07-1997/jw-07-hood.html?page=1.

Thank you for your answer, but I wasn't looking for a benchmark. My question was regarding the architecture of the Java plataform. Anyway, you should really take a look at your test/benchmark becouse StringBuilder should be faster in a single-thread enviroment (don't want to be rude, but it's not a good benchmark).

Also memory would be something good to test, to see if there are some auxiliary constructs used by StringBuffer or StringBuilder. I recommend you to make a single method, becouse the "concat" method is the same for all clases i. E: has the same API.

– santiagobasulto Dec 19 at 1:01 I agree StringBuilder should be faster, and a similar test here -> littletutorials. Com/2008/07/16/… does show that (also done in jre6). The question is why - perhaps an underlying architectural reason?

Further testing on a Windows 7 machine with 1Gb RAM yielded the expected results (ie StringBuilder faster) (previously tests were on an OSX machine)... perhaps different implementations utilising available memory differently, perhaps the host OS plays an important role as well? – binarycube Dec 21 at 0:46 No, the reason my friend is that your test is not good! If you have a minute read the introduction of this chapter from Dive into Python (It's python, not Java, sorry).

Diveintopython.Net/performance_tuning/timeit. Html – santiagobasulto Dec 21 at 2:03 Kudos to @santiagobasulto for pointing out single value test is meaningless - should have known better... but it looked like it was working OK ... ahh well... – binarycube Dec 21 at 8:07.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions