String concatenation: concat() vs + operator
No, not quite.
Firstly, there's a slight difference in semantics. If a
is null
, then a.concat(b)
throws a NullPointerException
but a+=b
will treat the original value of a
as if it were null
. Furthermore, the concat()
method only accepts String
values while the +
operator will silently convert the argument to a String (using the toString()
method for objects). So the concat()
method is more strict in what it accepts.
To look under the hood, write a simple class with a += b;
public class Concat {
String cat(String a, String b) {
a += b;
return a;
}
}
Now disassemble with javap -c
(included in the Sun JDK). You should see a listing including:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/ String;
18: astore_1
19: aload_1
20: areturn
So, a += b
is the equivalent of
a = new StringBuilder()
.append(a)
.append(b)
.toString();
The concat
method should be faster. However, with more strings the StringBuilder
method wins, at least in terms of performance.
The source code of String
and StringBuilder
(and its package-private base class) is available in src.zip of the Sun JDK. You can see that you are building up a char array (resizing as necessary) and then throwing it away when you create the final String
. In practice memory allocation is surprisingly fast.
Update: As Pawel Adamski notes, performance has changed in more recent HotSpot. javac
still produces exactly the same code, but the bytecode compiler cheats. Simple testing entirely fails because the entire body of code is thrown away. Summing System.identityHashCode
(not String.hashCode
) shows the StringBuffer
code has a slight advantage. Subject to change when the next update is released, or if you use a different JVM. From @lukaseder, a list of HotSpot JVM intrinsics.
Concatenation operator (+) vs. concat()
The concat method always produces a new String with the result of concatenation.
The plus operator is backed by StringBuilder creation, appending all String values you need and further toString() calling on it.
So, if you need to concatenate two values, concat() will be better choice. If you need to concatenate 100 values, you should use the plus operator or explicitly use StringBuilder (e.g. in case of appending in a cycle).
Difference between string.concat and the + operator in string concatenation
str.concat(" game");
has the same meaning as str + " game";
. If you don't assign the result back somewhere, it's lost. You need to do:
str = str.concat(" game");
What is the difference of + operator and concat() method in JavaScript
There are pretty the same but +
is more clear and for sure faster.
Look at this performance test and also see this
It is strongly recommended that assignment operators (+, +=) are used instead of the concat() method.
Difference between string.concat() and + operator
Not in this example.
If you concatenate several strings with + (e.g., "Hello " + user + "!"
), current compilers will use a StringBuilder to implement the + operator because this is faster than first creating the string for "Hello " + user
and then creating the final string. They probably don't do that for concat()
, so there would be a technical difference here.
Edit: see also String concatenation: concat() vs "+" operator and Is there a difference between String concat and the + operator in Java?.
StringBuilder vs. .concat vs. + Operator relative performance different in eclipse than command line?
On Oracle JDK 1.7 (javac 1.7.0_17), the "+" operator is still implemented using StringBuilder
, as shown by running javap -c
on the class to get the bytecode (only showing the loops here):
public static void plusOperator();
Code:
16: iload 4
18: ldc #10 // int 100000000
20: if_icmpge 53
23: new #11 // class java/lang/StringBuilder
26: dup
27: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V
30: aload_0
31: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: aload_1
35: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
38: aload_2
39: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
45: astore 5
47: iinc 4, 1
50: goto 16
public static void stringBuilder();
Code:
16: iload 4
18: ldc #10 // int 100000000
20: if_icmpge 50
23: new #11 // class java/lang/StringBuilder
26: dup
27: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V
30: aload_0
31: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: aload_1
35: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
38: aload_2
39: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: astore 5
44: iinc 4, 1
47: goto 16
The only difference between these two is that the version with "+" converts the StringBuilder
to a String
within the loop.
So the question becomes: why does your test show such different results for the same code. Or more completely, why is this not a valid micro-benchmark. Here are some possible reasons:
- You're counting wall-clock time. This means that you're actually measuring everything that the JVM is doing while running your test. Which includes garbage collection (which is important because you're creating a lot of garbage). You can mitigate this by getting the thread CPU time.
- You don't verify when or if HotSpot is compiling the methods. This is why you should do a warmup phase before any micro-benchmarks: basically, run your
main()
multiple times, before you run your actual test.
When to use String#concat() method in Java?
String#concat
and +
exist to provide a minimalistic set of operations on the type String.
They are not efficient if used multiple times.
But they have their own right as type operations "xxx" + "yyy"
you do not want to specify using a StringBuilder. (Furthermore there it is a compile time concatenation.)
StringBuffer
is a mistake IMHO. It is slower that the newer StringBuilder
as it is synchronized, but one would rarely add something rom two threads (unordered).
String::concat
may be a method reference useful for stream reduction or such.
String Concatenation using concat operator (+) or String.format() method
The first won't actually create any extra strings. It will be compiled into something like:
String str = new StringBuilder("This the String1 ")
.append(str1)
.append(" merged with Sting2 ")
.append(str2)
.toString();
Given that the second form requires parsing of the format string, I wouldn't be surprised if the first one actually runs quicker.
However, unless you've got benchmarks to prove that this is really a bit of code which is running too slowly for you, you shouldn't be too worried about the efficiency. You should be more worried about readability. Which code do you find more readable?
Related Topics
Java Processbuilder: Resultant Process Hangs
Will System.Currenttimemillis Always Return a Value ≫= Previous Calls
Do Line Endings Differ Between Windows and Linux
Relation Between Memory Host and Memory Arguments Xms and Xmx from Java
Distinguishing Between Java Threads and Os Threads
Java Refuses to Start - Could Not Reserve Enough Space For Object Heap
Why Maven Uses Jdk 1.6 But My Java -Version Is 1.7
How to Ping External Ip from Java Android
Error: Could Not Find or Load Main Class
Running Jmap Getting Unable to Open Socket File
How to Execute Bash Command With Sudo Privileges in Java
Growing Resident Memory Usage (Rss) of Java Process
React on Global Hotkey in a Java Program on Windows/Linux/Mac
How to Redirect Multiple Types of Users to Their Respective Activities
What Is the Most Appropriate Way to Store User Settings in Android Application
Example Images For Code and Mark-Up Q&As
Fast Bitmap Blur For Android Sdk
Official Reasons For "Software Caused Connection Abort: Socket Write Error"