字符串连接操作符(+)是把多个字符串合并为一个字符串的便利途径。要想产生单独一行的输出,或者构造一个字符串来表示一个较小的、大小固定的对象,使用连接操作符是非常合适的,但是它不适合运用在大规模的场景中。为连接n个字符串而重复的使用字符串连接操作符,需要n的平方级的时间
。这是由于字符串不可变(详见第17条)而导致的不幸结果。当两个字符串被连接在一起时,它们的内容都会被拷贝。
例如,下面的方法通过重复的为每个项目连接一行,构造出一个代表该账单声明的字符串:
// Inappropriate use of string concatenation - Performs poorly!
public String statement() {
String result = "";
for (int i = 0; i < numItems(); i++)
result += lineForItem(i); // String concatenation
return result;
}
如果项目的数量巨大,这个方法的执行时间就难以估算。为了获得可以接受的性能,请用StringBuilder代替String
,来存储构造过程中的账单声明:
public String statement() {
StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);
for (int i = 0; i < numItems(); i++)
b.append(lineForItem(i));
return b.toString();
}
从Java6以来,已经做了大量的工作使字符串连接变得更加快速,但是上述两种做法的性能差别还是很大:如果numItems返回100,并且lineForItem返回一个固定长度为80个字符的字符串,在我的机器上,第二种做法比第一种做法要块6.5倍。因为第一种做法的开销随项目数量而呈平方级增加,项目的数量越大,性能的差别就会越明显。注意,第二种做法预先分配了一个StringBuilder,使它大到足以容纳整个结果字符串,因此不需要自动扩展。即使使用默认大小的StringBuilder,它也仍然比第一种做法块5.5倍。
原因很简单:不要使用字符串连接操作符来合并多个字符串
,除非性能无关紧要。否则,应该使用StringBuilder的append方法。另一种做法是使用字符数组,或者每次只处理一个字符串,而不是将它们组合起来。
网友评论