Is += more efficient than concat? [duplicate]
I've been reading code produced by other developers on my team, they seem to favor using +=
for String concatenation, whereas I prefer using .concat()
as it feels easier开发者_开发技巧 to read.
I'm trying to prepare an argument as to why using .concat()
is better, and I'm wondering, is there any difference in efficiency between the two?
Which option "should" we be taking?
public class Stuff {
public static void main(String[] args) {
String hello = "hello ";
hello += "world";
System.out.println(hello);
String helloConcat = "hello ".concat("world");
System.out.println(helloConcat);
}
}
Since String is immutable in java, when you do a +
, +=
or concat(String)
, a new String is generated. The bigger the String gets the longer it takes - there is more to copy and more garbage is produced.
Today's java compilers optimizes your string concatenation to make it optimal, e.g.
System.out.println("x:"+x+" y:"+y);
Compiler generates it to:
System.out.println((new StringBuilder()).append("x:").append(x).append(" y:").append(y).toString());
My advice is to write code that's easier to maintain and read.
This link shows performance of StringBuilder vs StringBuffer vs String.concat - done right
It shouldn't matter. Modern day Java compilers, JVMs and JITs will optimize your code in such a way that differences are likely to be minimal. You should strive to write code that's more readable and maintainable for you.
I agree with @darioo and most other answers. Always put readability (and maintainability) first. (A modern JIT compiler should have no troubles with simple cases like these.)
Here is however the bytecode corresponding to your program. (Note that the +=
approach results in a StringBuilder
which is generally the preferred approach when constructing strings.)
// String hello = "hello";
0: ldc #2; //String hello
2: astore_1
// hello += "world";
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method StringBuilder."<init>"
10: aload_1
11: invokevirtual #5; //Method StringBuilder.append
14: ldc #6; //String world
16: invokevirtual #5; //Method StringBuilder.append
19: invokevirtual #7; //Method StringBuilder.toString
// System.out.println(hello);
22: astore_1
23: getstatic #8; //Field System.out
26: aload_1
27: invokevirtual #9; //Method PrintStream.println
// String helloConcat = "hello ".concat("world");
30: ldc #2; //String hello
32: ldc #6; //String world
34: invokevirtual #10; //Method String.concat
37: astore_2
// System.out.println(helloConcat);
38: getstatic #8; //Field System.out
41: aload_2
42: invokevirtual #9; //Method PrintStream.println
45: return
In terms of readability, I think you are very wrong. +
wins over .concat()
. If you are using +=
, you might want to think about StringBuilder.append
keeping the same StringBuilder
for the loop.
In terms of performance concat
is better than +
. so long as you only use one or perhaps two.
In the case of concat
, you will end up creating a String
object with a correctly sized char[]
. It's about as optimal as you can get.
For +
javac generates code that constructs a StringBuilder
to do the appending and then converts to a String
. From 1.5 you create:
- A
StringBuilder
(waste) - Initial
char[]
forStringBuilder
(waste) - If resulting sequence is too long, a second bigger
char[]
(waste) - The resulting
String
. - The
String
'schar[]
.
However, you rarely see concat
used because it is more difficult to read. The performance is almost certainly going to be a drop in the ocean compared to what else is going on (hint: try the back of an envelope before optimising).
You should do what you find is the shortest and clearest to you.
However, for your interest.
String hello = "hello " + "world";
Is the fastest as the compile combined the two String into one.
This is fastest for two Strings as it avoids creating StringBuilder.
String helloConcat = "hello ".concat(world);
However if you have more than two strings Using StringBuilder, either implicitly or explicitly is fastest.
In summary I would use + unless you have it in a loop in which case I might use StringBuilder explicitly to improve performance.
Concat is definitely a faster choice for two strings concatination, I don't know why javac internally uses
(new StringBuilder(String.valueOf(s1))).append(s2).toString()
instead of
s1.concat(s2)
for s1 += s2. See my answer to a similar question concatenation operator (+) vs concat()
I have found this artical and made this test :
public static void main(String[] args) {
String s1 = generateString();
String s2 = generateString();
String s3 = generateString();
String s4 = generateString();
String s5 = generateString();
String s6 = generateString();
long e = System.currentTimeMillis();
for(int i=0;i<10000000;i++){
//StringBuilder > concat> plus >StringBuffer >plusEqual(">"means faster than)
//concatPlus(s1 , s2 , s3 , s4 , s5 , s6);//4204ms
//concatBuilder(s1 , s2 , s3 , s4 , s5 , s6);//2562ms
//concatBuffer(s1 , s2 , s3 , s4 , s5 , s6);//4610ms
//concatPlusEqual(s1 , s2 , s3 , s4 , s5 , s6);//9843ms
//concatConcat(s1 , s2 , s3 , s4 , s5 , s6);//3036ms
}
System.out.println(System.currentTimeMillis()-e);
}
public static String concatPlusEqual(String s1, String s2, String s3, String s4,
String s5, String s6) {
String result = "";
result += s1;
result += s2;
result += s3;
result += s4;
result += s5;
result += s6;
return result;
}
public static String concatConcat(String s1, String s2, String s3, String s4,
String s5, String s6) {
String result = new String();
result.concat(s1);
result.concat(s2);
result.concat(s3);
result.concat(s4);
result.concat(s5);
result.concat(s6);
return result;
}
public static String concatBuffer(String s1, String s2, String s3, String s4,
String s5, String s6) {
return new StringBuffer(s1.length() + s2.length() + s3.length()
+ s4.length() + s5.length() + s6.length()).append(s1)
.append(s2).append(s3).append(s4).append(s5).append(s6)
.toString();
}
public static String concatBuilder(String s1, String s2, String s3, String s4,
String s5, String s6) {
return new StringBuilder(s1.length() + s2.length() + s3.length()
+ s4.length() + s5.length() + s6.length()).append(s1)
.append(s2).append(s3).append(s4).append(s5).append(s6)
.toString();
}
public static String concatPlus(String s1,String s2,String s3,String s4,String s5,String s6) {
return s1 + s2 + s3 + s4 + s5 + s6;
}
public static String generateString()
{
Random rng = new Random();
int length = 10;
String characters ="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char[] text = new char[length];
for (int i = 0; i < length; i++)
{
text[i] = characters.charAt(rng.nextInt(characters.length()));
}
return new String(text);
}
It looks like that StringBuilder
is fastest and +=
is slowest.
Just for reference!
精彩评论