String concatenation in Java - when to use +, StringBuilder and concat [duplicate]
Asked Answered
K

9

69

When should we use + for concatenation of strings, when is StringBuilder preferred and When is it suitable to use concat.

I've heard StringBuilder is preferable for concatenation within loops. Why is it so?

Thanks.

Kiehl answered 19/10, 2011 at 7:35 Comment(1)
first thing that comes to mind is that each and every time you use a plain String, you allocate an object (providing work to GarbageCollector), while using a StringBuilder or a StringBuffer keeps you working with a single object.Ephemera
T
49

I tend to use StringBuilder on code paths where performance is a concern. Repeated string concatenation within a loop is often a good candidate.

The reason to prefer StringBuilder is that both + and concat create a new object every time you call them (provided the right hand side argument is not empty). This can quickly add up to a lot of objects, almost all of which are completely unnecessary.

As others have pointed out, when you use + multiple times within the same statement, the compiler can often optimize this for you. However, in my experience this argument doesn't apply when the concatenations happen in separate statements. It certainly doesn't help with loops.

Having said all this, I think top priority should be writing clear code. There are some great profiling tools available for Java (I use YourKit), which make it very easy to pinpoint performance bottlenecks and optimize just the bits where it matters.

P.S. I have never needed to use concat.

Thulium answered 19/10, 2011 at 7:38 Comment(2)
I've only once ever used concat(), and that was to replace str -> "foo" + str with a method reference: "foo"::concat.Hamster
@Hamster interestingly, in the reference implementation, str -> "foo" + str will be a singleton (non-capturing lambda expression) whereas "foo"::concat will not be, because the runtime doesn’t recognize that the captured String instance is a constant.Epilogue
S
66

Modern Java compiler convert your + operations by StringBuilder's append. I mean to say if you do str = str1 + str2 + str3 then the compiler will generate the following code:

StringBuilder sb = new StringBuilder();
str = sb.append(str1).append(str2).append(str3).toString();

You can decompile code using DJ or Cavaj to confirm this :) So now its more a matter of choice than performance benefit to use + or StringBuilder :)

However given the situation that compiler does not do it for your (if you are using any private Java SDK to do it then it may happen), then surely StringBuilder is the way to go as you end up avoiding lots of unnecessary String objects.

Sympathizer answered 19/10, 2011 at 7:38 Comment(5)
Yes, but if you use + in a loop, the runtime will create a new StringBuilder for each iteration leading to a heavy performance penalty.Willis
you can have STringBuilder created before start of loop. If you create StringBuilder each time in loop then you will anyway losing previos data of StringBuilder.Sympathizer
@Sahil: The compiler or optimiser may fix that.Eliseo
str = new StringBuilder(str1).append(str2).append(str3).toString(); will it make difference in performance concern?Catholicize
If you want to achieve concatenation of str1, str2 and str3 then this is most optimal way to do it.Sympathizer
T
49

I tend to use StringBuilder on code paths where performance is a concern. Repeated string concatenation within a loop is often a good candidate.

The reason to prefer StringBuilder is that both + and concat create a new object every time you call them (provided the right hand side argument is not empty). This can quickly add up to a lot of objects, almost all of which are completely unnecessary.

As others have pointed out, when you use + multiple times within the same statement, the compiler can often optimize this for you. However, in my experience this argument doesn't apply when the concatenations happen in separate statements. It certainly doesn't help with loops.

Having said all this, I think top priority should be writing clear code. There are some great profiling tools available for Java (I use YourKit), which make it very easy to pinpoint performance bottlenecks and optimize just the bits where it matters.

P.S. I have never needed to use concat.

Thulium answered 19/10, 2011 at 7:38 Comment(2)
I've only once ever used concat(), and that was to replace str -> "foo" + str with a method reference: "foo"::concat.Hamster
@Hamster interestingly, in the reference implementation, str -> "foo" + str will be a singleton (non-capturing lambda expression) whereas "foo"::concat will not be, because the runtime doesn’t recognize that the captured String instance is a constant.Epilogue
R
27

From Java/J2EE Job Interview Companion:

String

String is immutable: you can’t modify a String object but can replace it by creating a new instance. Creating a new instance is rather expensive.

//Inefficient version using immutable String
String output = "Some text";
int count = 100;
for (int i = 0; i < count; i++) {
    output += i;
}
return output;

The above code would build 99 new String objects, of which 98 would be thrown away immediately. Creating new objects is not efficient.

StringBuffer/StringBuilder

StringBuffer is mutable: use StringBuffer or StringBuilder when you want to modify the contents. StringBuilder was added in Java 5 and it is identical in all respects to StringBuffer except that it is not synchronised, which makes it slightly faster at the cost of not being thread-safe.

//More efficient version using mutable StringBuffer
StringBuffer output = new StringBuffer(110);
output.append("Some text");
for (int i = 0; i < count; i++) {
  output.append(i);
}
return output.toString();

The above code creates only two new objects, the StringBuffer and the final String that is returned. StringBuffer expands as needed, which is costly however, so it would be better to initialise the StringBuffer with the correct size from the start as shown.

Rasorial answered 19/10, 2011 at 9:23 Comment(1)
plus 1 for book link. (Unable to add + sign as "Comments cannot contain that content" :) )Nutshell
S
8

If all concatenated elements are constants (example : "these" + "are" + "constants"), then I'd prefer the +, because the compiler will inline the concatenation for you. Otherwise, using StringBuilder is the most effective way.

If you use + with non-constants, the Compiler will internally use StringBuilder as well, but debugging becomes hell, because the code used is no longer identical to your source code.

Saccule answered 19/10, 2011 at 7:39 Comment(0)
F
5

My recommendation would be as follows:

  • +: Use when concatenating 2 or 3 Strings simply to keep your code brief and readable.
  • StringBuilder: Use when building up complex String output or where performance is a concern.
  • String.format: You didn't mention this in your question but it is my preferred method for creating Strings as it keeps the code the most readable / concise in my opinion and is particularly useful for log statements.
  • concat: I don't think I've ever had cause to use this.
Fridge answered 19/10, 2011 at 7:45 Comment(1)
concat() damn fast if you're concatenating two String.Thuythuya
K
3

Use StringBuilder if you do a lot of manipulation. Usually a loop is a pretty good indication of this.

The reason for this is that using normal concatenation produces lots of intermediate String object that can't easily be "extended" (i.e. each concatenation operation produces a copy, requiring memory and CPU time to make). A StringBuilder on the other hand only needs to copy the data in some cases (inserting something in the middle, or having to resize because the result becomes to big), so it saves on those copy operations.

Using concat() has no real benefit over using + (it might be ever so slightly faster for a single +, but once you do a.concat(b).concat(c) it will actually be slower than a + b + c).

Kirtle answered 19/10, 2011 at 7:46 Comment(0)
M
3

Use + for single statements and StringBuilder for multiple statements/ loops.

Machicolate answered 19/10, 2011 at 9:11 Comment(0)
S
1

The performace gain from compiler applies to concatenating constants. The rest uses are actually slower then using StringBuilder directly.

There is not problem with using "+" e.g. for creating a message for Exception because it does not happen often and the application si already somehow screwed at the moment. Avoid using "+" it in loops.

For creating meaningful messages or other parametrized strings (Xpath expressions e.g.) use String.format - it is much better readable.

Seligmann answered 19/10, 2011 at 7:59 Comment(0)
A
1

I suggest to use concat for two string concatination and StringBuilder otherwise, see my explanation for concatenation operator (+) vs concat()

Acrolith answered 6/12, 2012 at 8:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.