Is chain of StringBuilder.append more efficient than string concatenation?

You have to balance readability with functionality.

Let’s say you have the following:

String str = "foo";
str += "bar";
if(baz) str += "baz";

This will create 2 string builders (where you only need 1, really) plus an additional string object for the interim. You would be more efficient if you went:

StringBuilder strBuilder = new StringBuilder("foo");
strBuilder.append("bar");
if(baz) strBuilder.append("baz");
String str = strBuilder.toString();

But as a matter of style, I think the first one looks just fine. The performance benefit of a single object creation seems very minimal to me. Now, if instead of 3 strings, you had 10, or 20, or 100, I would say the performance outweighs the style. If it was in a loop, for sure I’d use the string builder, but I think just a couple strings is fine to do the ‘sloppy’ way to make the code look cleaner. But… this has a very dangerous trap lurking in it! Read on below (pause to build suspense… dun dun dunnnn)

There are those who say to always use the explicit string builder. One rationale is that your code will continue to grow, and it will usually do so in the same manner as it is already (i.e. they won’t take the time to refactor.) So you end up with those 10 or 20 statements each creating their own builder when you don’t need to. So to prevent this from the start, they say always use an explicit builder.

So while in your example, it’s not going to be particularly faster, when someone in the future decides they want a file extension on the end, or something like that, if they continue to use string concatenation instead of a StringBuilder, they’re going to run into performance problems eventually.

We also need to think about the future. Let’s say you were making Java code back in JDK 1.1 and you had the following method:

public String concat(String s1, String s2, String s3) {
    return s1 + s2 + s3;
}

At that time, it would have been slow because StringBuilder didn’t exist.

Then in JDK 1.3 you decided to make it faster by using StringBuffer (StringBuilder still doesn’t exist yet). You do this:

public String concat(String s1, String s2, String s3) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    sb.append(s3);
    return sb.toString();
}

It gets a lot faster. Awesome!

Now JDK 1.5 comes out, and with it comes StringBuilder (which is faster than StringBuffer) and the automatic transation of

return s1 + s2 + s3;

to

return new StringBuilder().append(s1).append(s2).append(s3).toString();

But you don’t get this performance benefit because you’re using StringBuffer explicitly. So by being smart, you have caused a performance hit when Java got smarter than you. So you have to keep in mind that there are things out there you won’t think of.

Leave a Comment