StringBuilder/StringBuffer vs. “+” 运算符

2022-09-01 00:54:57

我正在阅读“Better, Faster, Light Java”(由Bruce Tate和Justin Gehtland撰写),并且熟悉敏捷类型团队的可读性要求,例如Robert Martin在他的干净编码书中讨论的内容。在我现在所在的团队中,我被明确告知不要使用运算符,因为它会在运行时创建额外(和不必要的)字符串对象。+

但是这篇文章,写在04年,讨论了对象分配如何大约是10个机器指令。(基本上是免费的)

它还讨论了GC如何有助于降低这种环境中的成本。

使用 或 之间的实际性能权衡是什么?(在我的情况下,这只是因为我们仅限于Java 1.4.2。+StringBuilderStringBufferStringBuffer

StringBuffer对我来说,这会导致丑陋的、可读性较差的代码,正如泰特书中的几个例子所证明的那样。并且是线程同步的,它似乎有自己的成本,超过了使用运算符的“危险”。StringBuffer+

想法/意见?


答案 1

使用串联由编译器转换为操作。StringStringBuilder

为了了解编译器是如何做到的,我将取一个示例类,编译它并使用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 ?");
}

反编译的类:

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());
}
  • 编译器在编译时执行了该操作。method1
  • 在串联上等效于手动使用 。method2StringStringBuilder
  • 关于串联肯定是不好的,因为编译器正在创建第二个而不是重用前一个。method3StringStringBuilder

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


答案 2

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

当然,有时使用是有意义的 - 特别是当您在循环中创建字符串时,特别是如果您不确定循环中是否会有很少的迭代。请注意,这不仅仅是创建新对象的问题 - 而是复制已追加的所有文本数据的问题。还要记住,如果你不考虑垃圾回收,对象分配只是“基本上免费的”。是的,如果当前一代有足够的空间,那基本上是增加指针的问题......但:StringBuffer

  • 那段记忆一定在某个时候被清除了。那不是免费的。
  • 您正在缩短需要下一个 GC 的时间。GC不是免费的。
  • 如果你的对象存在于下一代,它可能需要更长的时间才能被清理 - 再次,不是免费的。

所有这些东西都相当便宜,因为它“通常”不值得将设计从优雅中弯曲出来以避免创建对象......但你不应该把它们视为自由的。

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

String x = a + b + c + d;

至少与以下方法一样高效:

StringBuffer buffer = new StringBuffer();
buffer.append(a);
buffer.append(b);
buffer.append(c);
buffer.append(d);
String x = buffer.toString();

推荐