StringBuilder/StringBuffer与"+"运算符

avg*_*tvs 35 java performance readability

我正在阅读" 更好,更快,更轻的Java "(由Bruce Tate和Justin Gehtland撰写)并且熟悉敏捷类型团队的可读性要求,例如Robert Martin在其清晰的编码书中所讨论的内容.在我现在的团队中,我被告知明确不使用+运算符,因为它在运行时创建了额外的(和不必要的)字符串对象.

但是这篇文章,写于04年,讨论了对象分配是关于10个机器指令的.(基本上免费)

它还讨论了GC如何帮助降低此环境中的成本.

什么是使用之间的实际性能的权衡+,StringBuilder还是StringBuffer?(就我而言,它StringBuffer仅限于Java 1.4.2.)

StringBuffer对我来说导致丑陋,不太可读的代码,正如Tate的书中的几个例子所示.而且StringBuffer是线程同步的,这似乎有它自己的成本是大于中使用了"危险" +操作.

思想/意见?

gab*_*uzo 49

使用String连接StringBuilder由编译器转换为操作.

为了看看编译器是如何做的,我将采用一个示例类,编译它并用jad对其进行反编译,看看生成的字节码是什么.

原班级:

public void method1() {
    System.out.println("The answer is: " + 42);
}

public void method2(int value) {
    System.out.println("The answer is: " + value);
}

public void method3(int value) {
    String a = "The answer is: " + value;
    System.out.println(a + " what is the question ?");
}
Run Code Online (Sandbox Code Playgroud)

反编译的类:

public void method1()
{
    System.out.println("The answer is: 42");
}

public void method2(int value)
{
    System.out.println((new StringBuilder("The answer is: ")).append(value).toString());
}

public void method3(int value)
{
    String a = (new StringBuilder("The answer is: ")).append(value).toString();
    System.out.println((new StringBuilder(String.valueOf(a))).append(" what is the question ?").toString());
}
Run Code Online (Sandbox Code Playgroud)
  • method1编译器上执行编译时的操作.
  • method2String级联相当于手动使用StringBuilder.
  • method3String级联的编译器创建第二个肯定是不好的StringBuilder,而不是重用前一个.

所以我的简单规则是连接是好的,除非你需要再次连接结果:例如在循环中或当你需要存储中间结果时.

  • 在Java语言规范中,它建议这就是编译器会做的事情,留下它不会的可能性.15.18.1.2字符串连接的优化 (3认同)

Jon*_*eet 22

您的团队需要了解避免重复字符串连接原因.

里面肯定时间的时候是有意义的使用StringBuffer-特别是当你在一个循环中创建一个字符串,特别是如果你不能肯定会有在循环几次迭代.请注意,这不仅仅是创建新对象的问题 - 而是复制已经附加的所有文本数据.还要记住,如果不考虑垃圾收集,对象分配只是"基本上免费".是的,如果当前一代有足够的空间,那基本上就是增加一个指针......但是:

  • 那个记忆必须在某个时候被清除.这不是免费的.
  • 您缩短了直到需要下一个GC的时间.GC不是免费的.
  • 如果你的物体生活在下一代,可能需要更长时间才能清理 - 再次,不是免费的.

所有这些东西都相当便宜,因为它"通常"不值得将设计从优雅中剔除以避免创造物体......但你不应该认为它们是免费的.

另一方面,在StringBuffer不需要中间字符串的情况下使用是没有意义的.例如:

String x = a + b + c + d;
Run Code Online (Sandbox Code Playgroud)

至少和以下一样有效:

StringBuffer buffer = new StringBuffer();
buffer.append(a);
buffer.append(b);
buffer.append(c);
buffer.append(d);
String x = buffer.toString();
Run Code Online (Sandbox Code Playgroud)


adr*_*ser 5

对于小型连接,您可以简单地使用String和+以便于阅读.性能不会受到影响.但是,如果你正在进行大量的连接操作,请选择StringBuffer.