88

I'm trying to understand what the best practice is and why for concatenating string literals and variables for different cases. For instance, if I have code like this

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String).append("CCCCCCCCCCC").append(D_String)
    .append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

Is this the way to do it? From this post, I noticed that the + operator on Strings creates a new instance of StringBuilder, concatenates the operands, and returns a String conversion, which seems like a lot more work than just calling .append(); so if that's true, then that is out of the question. But what about String.concat()? Is it proper to use .append() for every concatenation? Or just for variables, and literals are okay to append with .concat()?

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String.concat("CCCCCCCCCCC")).append(D_String
    .concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));

What are the general rules for best practices and performance for going about these situations? Is my assumption correct on + and it should really just not be used?

Community
  • 1
  • 1
Nick Rolando
  • 25,176
  • 13
  • 72
  • 111
  • I think basically you've got it. Opinions differ as to whether String + "really should just not be used". The point is that you understand the consequences – ControlAltDel Apr 09 '12 at 19:54

9 Answers9

186

+ operator

String s = s1 + s2

Behind the scenes this is translated to:

String s = new StringBuilder(s1).append(s2).toString();

Imagine how much extra work it adds if you have s1 + s2 here:

stringBuilder.append(s1 + s2)

instead of:

stringBuilder.append(s1).append(s2)

Multiple strings with +

Worth to note that:

String s = s1 + s2 + s3 + ... +sN

is translated to:

String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();

concat()

String s = s1.concat(s2);

String creates char[] array that can fit both s1 and s2. Copies s1 and s2 contents to this new array. Actually requires less work then + operator.

StringBuilder.append()

Maintains an internal char[] array that grows when needed. No extra char[] is created if the internal one is sufficiently big.

stringBuilder.append(s1.concat(s2))

is also performing poorly because s1.concat(s2) creates an extra char[] array and copies s1 and s2 to it just to copy that new array contents to internal StringBuilder char[].

That being said you should use append() all the time and append raw strings (your first code snippet is correct).

Tomasz Nurkiewicz
  • 311,858
  • 65
  • 665
  • 652
  • Thanks for your help, and the in-depth explanation; that's what I really needed. – Nick Rolando Apr 09 '12 at 20:07
  • 12
    Although newer versions of the compiler automatically optimize the + operator to a string builder it isn't necessarily a good thing to assume it will as older versions don't. There is a very important topic that is being ignored in this whole discussion which is actually one of the main purposes for StringBuilder which is the string pool. Using a string builder keeps everything as a char[] and doesn't create an intermediate String like the + operator did before compiler optimizations(used to just do a concat). Using concat creates an intermediate String object which is cached but not used. – LINEMAN78 Apr 09 '12 at 20:08
  • So if I'm doing a *one-time statement* (not multiple statements accross a method) concatenation on several different strings. It would be okay to use `+` on the String objects instead of creating a `StringBuilder` for this one time concatenation, since it will basically do the same thing? – Nick Rolando Apr 09 '12 at 20:13
  • 1
    And if I want to concat only a character, is it better to use .append('\n') instead of .append("\n")? As a character is a primitive type, and a String is an Object? – vrwim Oct 07 '13 at 10:16
  • 3
    _Effective Java 2-nd edition_: __Using the string concatenation operator repeatedly to concatenate n strings requires time quadratic in n.__ So is it still relevant? – gkiko Mar 17 '15 at 08:49
  • @gkiko: Well, I think that you can safely ignore it if you're coding for modern compilers. The string concatenation optimization is mentioned in the Java Language Specification of 1.6 ( https://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.1.2 ), although I'm not sure since when it was actually implemented in the Sun/Oracle VM. If it REALLY matters to you, have a look at the generated bytecode before doing String +, but I think it's the easiest and most readable way (and I've been routinely doing StringBuilder.append for YEARS :). – Franz D. Sep 28 '18 at 20:48
16

The compilier optimize the + concatenation.

So

int a = 1;
String s = "Hello " + a;

is transformed into

new StringBuilder().append("Hello ").append(1).toString();

There an excellent topic here explaining why you should use the + operator.

Andy Turner
  • 122,430
  • 10
  • 138
  • 216
3

Optimization is done automatically by the compiler.

The Java2 compiler will automatically convert the following:

String s = s1 + s2; 

to

String s = (new StringBuffer()).append(s1).append(s2).toString();

Taken straight from the Java Best Practices on Oracles website.

BoldAsLove
  • 600
  • 2
  • 12
2

You should always use append.

concat create a new String so it's pretty like + I think.

If you concat or use + with 2 final String the JVM can make optimisation so it's the same as doing append in this case.

alain.janinm
  • 19,035
  • 10
  • 56
  • 103
1

If you concat exactly two Strings use String.concat (creates a new String by creating a new char-array that fits both Strings and copys both Strings' char arrays into it).

If you concat multiple (more than two) Strings in one line, use + or StringBuilder.append, it doesn't matter, since the compiler converts + to StringBuilder.append. This is good for multiple Strings because it maintains one char array that grows as needed.

If you concat multiple Strings over multiple lines create one StringBuilder and use the append-method. In the end when you are done appending Strings to the StringBuilder use it's .toString()-method to create a String out of it. For concatting in multiple lines this is faster than the second method, since the second method would create a new StringBuilder on each line, append the Strings and then cast back to String, while the third method only uses one StringBuilder for the whole thing.

Dakkaron
  • 4,941
  • 2
  • 32
  • 48
1

I personally prefer the Strings.format(), simple easy to read one-line string formatter.

String b = "B value";
String d = "D value";
String fullString = String.format("A %s C %s E F", b, d);
// Output: A B value C D value E F
T04435
  • 7,493
  • 1
  • 41
  • 47
0

Use + operator is best practice, it is also simple and readable.

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method.

Offical document: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html

Do Nhu Vy
  • 33,131
  • 37
  • 143
  • 202
0

in byte code level there is not different and we are not compromising effeciancy there. In case of executing byte code level, it must go through non-inline operator overloading method for + by calling append. then in assembly language level (Java is written in C and C produces assemblies similar to assembly, there will be extra register call to store + method call in the stack and there will additional push. (in reality, cross-compiler might optimise + operator call, in that case making it no difference with efficiancy.)

It is a good practice to have one way to increase the readability. :)

Shevon Silva
  • 139
  • 1
  • 3
0

All answers are pretty good and explanatory. But I felt exploration around other string concatenation techniques would also help like - Guava Joiner, Streams, String.format etc.

For complete details over performance of each concatenation technique java-string-concatenation-which-way-is-best.

In Brief, concatenation performance varies with no. of strings to concatenate. For example - to concatenate 1-10 strings, these techniques works best - StringBuilder, StringBuffer and Plus Operator. And to concatenate 100s of strings - Guava Joiner, apache's stringsUtils library also works great.

Please go through the above blog. It really explains performance efficiency very well.

Thanks.

coderAJ
  • 310
  • 4
  • 15