给定下面的2个toString()实现,哪个是首选的:
public String toString(){
return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}
or
public String toString(){
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:").append(b)
.append(", c:").append(c)
.append("}")
.toString();
}
?
更重要的是,鉴于我们只有3个属性,它可能不会有什么不同,但在什么时候你会从+ concat切换到StringBuilder?
在大多数情况下,你不会看到这两种方法之间的实际区别,但很容易构建一个像下面这样的最坏情况:
public class Main
{
public static void main(String[] args)
{
long now = System.currentTimeMillis();
slow();
System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");
now = System.currentTimeMillis();
fast();
System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
}
private static void fast()
{
StringBuilder s = new StringBuilder();
for(int i=0;i<100000;i++)
s.append("*");
}
private static void slow()
{
String s = "";
for(int i=0;i<100000;i++)
s+="*";
}
}
输出结果为:
slow elapsed 11741 ms
fast elapsed 7 ms
问题是,+=追加到一个字符串重构一个新的字符串,所以它的代价是字符串长度的线性(两者的和)。
对于你的问题
第二种方法更快,但可读性较差,也更难维护。
正如我所说,在你的具体情况下,你可能看不到区别。
关键在于你是在一个地方写一个连接,还是在一段时间内把它积累起来。
对于您给出的示例,显式使用StringBuilder是没有意义的。(请查看第一个案例的编译代码。)
但是如果你正在构建一个字符串,例如在一个循环中,使用StringBuilder。
为了澄清,假设hugeArray包含数千个字符串,代码如下:
...
String result = "";
for (String s : hugeArray) {
result = result + s;
}
与以下相比非常浪费时间和内存:
...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
sb.append(s);
}
String result = sb.toString();