为什么字符串拼接需要这么长时间?

3

我在循环中拼接字符串,但这需要很长时间,为什么会这样?

for (String object : jsonData) {
    counter++;
    finalJsonDataStr += object;
}

变量object是一段JSON,长度最多70个字符,循环大约执行50k次。

我知道有些人建议使用StringBufferStringBuilder,但这个链接说它并没有性能提升:Java中toString()方法中StringBuilder与String拼接的比较


2
你有比“年龄”更具体的度量标准吗? - Jeroen Vannevel
是的,大约需要2分钟时间... - Ondrej Tokar
3个回答

9

使用字符串构建器来追加字符串。

当您进行字符串连接时,Java实际上是创建一个新的字符串,并将连接的结果存储在其中。如果多次执行此操作,则会不必要地创建大量字符串。

尝试使用:

StringBuilder sb = new StringBuilder();
for (String object : jsonData) { 
    counter++; 
    sb.append(object.toString());  //this does the concatenation internally
                                   //but is very efficient
}

finalJsonDataStr = sb.toString(); //this gives you back the whole string 

注:

在进行以下操作时:

myString = "hello " + someStringVariable + " World!" + " My name is " + name;

编译器足够智能,可以用一个StringBuilder代替所有这些,例如:
myString = new StringBuilder("hello ")
                      .append(someStringVariable)
                      .append(" World!")
                      .append(" My name is ")
                      .append(name).toString();

但出于某些我不知道的原因,当串联发生在循环内部时,它就无法执行。


如果构建的字符串超过16个字符,请考虑为您的StringBuilder分配更大的初始容量。 StringBuilder sb = new StringBuilder(1000); - BoDidely
1
这个语句指的是当连接发生在循环内部时,它就不会执行。有关此语句的任何参考资料吗? - Suresh Atta

1
你应该使用 StringBufferStringBuilder
当你使用加号连接字符串时,会创建一个 StringBuilder 对象,将字符串拼接在一起,并通过 StringBuildertoString() 方法返回一个新的字符串。所以想象一下,这样的对象创建和字符串操作重复了 50k 次。如果你只实例化一个 StringBuilder,并且只是追加字符串,那么效果会更好...
这个答案可能对你有用: 连接运算符(+)与 concat()

0
在深入讨论实际问题之前,先了解一下内部连接的工作原理。
String testString ="str"+"ingcon"+"catenation";  

如果我们将上述声明的字符串打印到控制台并查看,结果是字符串连接。这是正确的,加号运作正常。这里实际的问题是,加号符号如何产生魔力?它不是字符串的正常数学加法吗?下面的代码片段显示了加号代码实际执行的内容。
 StringBuilder compilerGeneratedBuilder = new StringBuilder();  
 compilerGeneratedBuilder.append("str");  
 compilerGeneratedBuilder.append("ingcon");  
 compilerGeneratedBuilder.append("catenation");  
 String finalString = compilerGeneratedBuilder.toString(); 

更多...

循环50K次是一个需要考虑的性能阻塞。

在这种情况下,使用带有append方法的StringBuilder。因为concat(+)每次创建一个新的字符串构建器对象。这会导致创建50k个对象。

使用单个StringBuilder和append方法,您可以节省对象创建的时间以及内存。


@JonathanDrapeau 我在谈论字符串连接的运行时行为。:http://codeinventions.blogspot.in/2014/08/compiler-version-string-concatenation.html - Suresh Atta
@JonathanDrapeau 这一点并不令人困惑。在底层,Java使用StringBuilder来进行连接操作。当在循环中多次使用它进行连接操作时,每次都会创建一个新的构建器,这会导致性能受到影响。 - Dioxin
@JonathanDrapeau 我是那篇文章的作者 :) 我会添加的。 - Suresh Atta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接