我一直在阅读我的团队中其他开发人员生成的代码,他们似乎赞成使用+=
进行字符串连接,而我更喜欢使用.concat()
,因为它更容易阅读。
我正在尝试准备一个论据,为什么使用.concat()
更好,我想知道,两者之间的效率有什么不同吗?
我们应该选择哪个选项?
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);
}
}
答案 0 :(得分:10)
没关系。现代Java编译器,JVM和JIT将以这样的方式优化您的代码,使差异可能很小。您应该努力编写更易读和可维护的代码。
答案 1 :(得分:9)
由于String在java中是不可变的,因此当您执行+
,+=
或concat(String)
时,会生成一个新的String。 String越大,所需的时间越长 - 复制的次数越多,产生的垃圾就越多。
今天的java编译器优化了你的字符串连接以使其最佳,例如
System.out.println("x:"+x+" y:"+y);
编译器将其生成为:
System.out.println((new StringBuilder()).append("x:").append(x).append(" y:").append(y).toString());
我的建议是编写更易于维护和阅读的代码。
此链接显示StringBuilder vs StringBuffer vs String.concat - done right
的效果答案 2 :(得分:5)
我同意@darioo和其他大多数答案。始终首先考虑可读性(和可维护性)。 (对于像这样的简单情况,现代JIT编译器应该没有麻烦。)
然而,这是与您的程序对应的字节码。 (请注意,+=
方法会产生StringBuilder
,这通常是构造字符串时的首选方法。)
// 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
答案 3 :(得分:3)
就可读性而言,我认为你错了。 +
胜过.concat()
。如果您使用的是+=
,则可能需要考虑StringBuilder.append
为循环保持相同的StringBuilder
。
在效果方面concat
优于+
。只要你只使用一个或两个。
如果是concat
,您最终会创建一个String
对象,其大小正确char[]
。它就像你能得到的那样最佳。
对于+
,javac会生成构造StringBuilder
以执行追加然后转换为String
的代码。从1.5创建:
StringBuilder
(废物)char[]
(废物)StringBuilder
char[]
(浪费)String
。String
的{{1}}。但是,您很少看到char[]
使用,因为它更难阅读。与其他情况相比,表现几乎可以肯定是海洋中的下降(提示:在优化之前尝试信封的背面)。
答案 4 :(得分:1)
你应该做你认为最短,最清楚的事情。
然而,为了您的兴趣。
String hello = "hello " + "world";
最快,因为编译将两个String组合成一个。
对于两个字符串来说这是最快的,因为它避免了创建StringBuilder。
String helloConcat = "hello ".concat(world);
但是,如果您有两个以上的字符串使用StringBuilder,则隐式或显式最快。
总之,我会使用+,除非你在循环中使用它,在这种情况下我可能会明确地使用StringBuilder来提高性能。
答案 5 :(得分:1)
Concat绝对是两个字符串连接的更快选择,我不知道为什么javac内部使用
(new StringBuilder(String.valueOf(s1))).append(s2).toString()
而不是
s1.concat(s2)
表示s1 + = s2。请参阅我对类似问题concatenation operator (+) vs concat()
的回答答案 6 :(得分:0)
我找到了这个artical并做了这个测试:
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);
}
StringBuilder
似乎最快, +=
最慢。
仅供参考!