I had a debate a while back about the efficiency of string concatenation using the ‘+’ operator.
This recently came around again on a Java forum that I had posted on.
I’d seen some code that had concatenated several strings using StringBuffer.
The code was pre-JDK 5 and we were re-using bits of it for a project I was on. Since StringBuffer wasn’t needed
as no synchronization was being performed, the first refactoring prior to migration was changing StringBuffer to StringBuilder.
What struck me as odd was that the (now StringBuilder) object wasn’t being used inside of any sort of loop structure or any other programmatic
structure that would warrant the creation of a StringBuilder object.
The code actually looked similar to this:
public String message1(String value1, String value2) { StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append("Value ") .append(value1) .append(" is greater than ") .append(value2); return messageBuilder.toString(); }
Since I thought this to be a bit overkill, I refactored the code to now look similar to this:
public String message1(String value1, String value2) { return "Value " + value1 + " is greater than " + value2; }
Let The Debate Ensue!
This started quite the performance debate. Many of my colleagues on the project were under the impression that StringBuilder concatenation
is ALWAYS faster than String concatenation using the + operator. Many of them also thought it bad practice to use anything but StringBuilder
when concatenating multiple Strings and had gotten in the habit of using Builder’s for all concatenation in all code to “speed things up”.
I will agree that there are certain instances where using StringBuilder performs better than using Strings and +. Loop structures are one such
case. Appending to a String is much faster inside a loop structure with a StringBuilder (provided the builder was created outside the loop
structure where the appending occurs) than using + or +=.
But StringBuilder isn’t a one-stop shop for String performance enhancement by any means.
Used in the above code example it does 2 things:
1. Makes the code uglier. Granted, this is my own opinion and I’m sure that some might disagree. I personally feel
that the chained calls to append()
are ugly when used like this. I think that in cases like this, using + to concatenate
Strings is less intrusive and makes the code easier to read.
2. IT ACTUALLY HURTS PERFORMANCE! – This is was the core of the above debate. Many had taken the StringBuilder for performance
pattern as gospel and had never looked into when this is applicable and when it isn’t.
If you don’t believe me, try a simple test of timing the calls of the above methods for yourself ( I recommend using
System.nanoTime()
instead of System.currentTimeMillis()
).
If your a bit more curious – take a look at the actual bytecode that is generated from each of the methods using a tool like ASM!
This is where things really get interesting!