java - 在Java中stringbuild VS String toString( )

  显示原文与译文双语对照的内容

给定下面的2 toString() 实现,哪一个是首选的:


public String toString(){
 return"{a:"+ a +", b:" + b +", c:" + c +"}";
}

或者


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个属性,它可能没有区别,但是在什么时候你将 switch 从 + 连接到 StringBuilder?

时间:

在一个地方或者累积在它的上方time,关键是无论你在编写一个串联所有的。

对于你给出的示例,显式使用 StringBuilder 是没有意义的。 ( 查看你的第一个案例的编译代码。)

但是如果要在循环内部构建字符串 比如,请使用 StringBuilder 。

要澄清,假设hugeArray包含数以千计的字符串,如:


...
String result ="";
for (String s : hugeArray) {
 result = result + s;
}

是非常time-和 memory-wasteful,与:


...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
 sb.append(s);
}
String result = sb.toString();

我喜欢:


String.format("{a: %s, b: %s, c: %s}", a, b, c );

因为它很短易读。

我的意思跟 为速度优化这个循环中的,除非你使用它有一个非常高的重复次数已经度量了性能差异。

我同意,如果你必须输出大量参数,这里表单会使( 就像一个评论) 变得混乱。 在这种情况下,我将 switch 改为更易读的表单( 在马特b,的答案多半是使用 ToStringBuilder apache-commons,被视为理所当然。),并再次忽略性能。

在大多数情况下,你不会看到这两种方法之间的实际差异,但是很容易构建一个最糟糕的案例场景:


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

问题是 += 附加到一个字符串重新构造一个新字符串,因此它花费的时间与字符串( 两者的总和)的长度不同。

所以- 回答你的问题:

第二种方法会更快,但它的可读性和维护难度都比较低。 就像我所说,在你的特定情况下你可能看不到。

Apache Commons-Lang有一个 ToStringBuilder类,它非常易于使用。 它既能处理 append-logic,也能很好地格式化你的toString 。


public void toString() {
 ToStringBuilder tsb = new ToStringBuilder(this);
 tsb.append("a", a);
 tsb.append("b", b)
 return tsb.toString();
}

将返回看起来像 com.blah.YourClass@abc1321f[a=whatever, b=foo]

或者使用链接更精简的形式:


public void toString() {
 return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

或者,如果要使用反射来包含类的每个字段:


public String toString() {
 return ToStringBuilder.reflectionToString(this);
}

你也可以自定义ToString的样式,如果你想要。

我可以指出,如果你要遍历一个集合并使用 StringBuilder,你可能需要签出 Apache Commons LangStringUtils.join() ( 口味不同)

无论性能如何,它都会节省你创建StringBuilders和循环的机会,比如 millionth的时间。

...