【问题标题】:When is the + operator faster than a StringBuilder? [duplicate]+ 运算符何时比 StringBuilder 快? [复制]
【发布时间】:2014-10-18 23:47:10
【问题描述】:

过去,我一直认为在构建带有变量的字符串时应该使用StringBuilderappend(String),而不是string += split[i]。在什么情况下这是准确的?我问是因为通常情况下,如果我要写以下内容:

String[] split = args; // command line arguments or whatever
String myString = "";
for (int i = 0; i < split.length; i++) {
    myString += split[i];
}

我的 IDE 告诉我应该将其转换为使用 StringBuilder。但是,写这样的东西:

StringBuilder build = new StringBuilder();
build.append("the ").append(build.toString()).append(" is bad").append(randomvar);
build.toString();

当我应该使用 String 时,IntelliJ 实际上将使用 StringBuilder 列为性能问题。它被列为性能问题这一事实表明它实际上可能会导致问题,而不是只是稍微慢一点。

我确实注意到第一个示例是一个循环,而第二个不是 - 是一个 StringBuilder 推荐用于大量连接,但普通连接更适合非循环情况(这也意味着在循环中运算符 +=将被使用,而在循环之外它可能是"the " + build.toString() + " is bad" + randomVar - 是+=问题而不是+?)

【问题讨论】:

  • 这不是很容易测试吗?就像为 10000 个追加 vs + 操作放置一个 for 循环一样。如果字符串是已知的,那么 + 可以被编译器优化。
  • + 运算符在整个操作由正好连接两个字符串组成时总是更有效。
  • 我认为它不是重复的,因为这更多地在于它在循环中和不在循环中的区别。
  • @DziNeIT 这是重复的。只需检查这些问题的答案,其中也涵盖了循环内的串联。
  • @ajb 这不是过早优化的情况...

标签: java


【解决方案1】:

字符串连接在后台转换为对 StringBuilder.append() 的调用。

字符串文字连接被(或至少可以)转换为单独的字符串文字。

您可能在循环中使用了一个字符串变量(不仅仅是两个文字),因此 Java 不能只用文字替换它;它必须使用 StringBuilder。这就是为什么在循环中进行字符串连接应该使用单个 StringBuilder 来完成,否则 Java 最终会在每次循环迭代时创建另一个 StringBuilder 实例。

另一方面,是这样的:

String animals = "cats " + "dogs " + "lizards ";

将(或可以)用单个字符串文字替换(由 Java,而不是您),因此使用 StringBuilder 实际上会适得其反。

【讨论】:

    【解决方案2】:

    从 java 1.5 开始,String + 运算符被转换为对 StringBuilder 的调用。

    在您的示例中,循环应该更慢,因为 + 运算符每次通过循环都会创建一个新的 StringBuilder 实例。

    【讨论】:

    • 这个答案有点埋没了。 + 操作符更糟糕,因为它每次都会创建一个新的StringBuilder这是一个 O(N) 操作。当你循环执行时,这意味着整个事情是 O(N^2)。
    【解决方案3】:

    编译器实际上会在编译之前将它们都转换为相同的形式,因此两者都不会导致任何性能差异。在这种情况下,您希望使用可用的最短且最易读的方法。

    "一个实现可以选择执行转换和连接 一步避免创建然后丢弃中间体 字符串对象。提高重复字符串的性能 连接,Java 编译器可以使用 StringBuffer 类或 减少中间字符串对象数量的类似技术 通过评估表达式创建的。

    对于原始类型,实现也可以优化掉 通过直接从原语转换来创建包装器对象 输入一个字符串。”

    来源:http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.18.1.2

    【讨论】:

    • 不是在第一种情况下,至少编译器不会创建一个比循环寿命更长的StringBuilder——它不是那么聪明。第一种情况仍应手动优化。
    【解决方案4】:

    对于小连接,您可以使用 + 运算符,没有任何问题。当我们需要连接大字符串时会指示 StringBuffer,因此使用此类您还可以节省内存和处理器的时间。

    您可以使用 + 运算符尝试连接 100 万个单词进行测试,并使用 StringBuffer 运行相同的测试以自己查看不同。

    【讨论】:

    • 不要混用StringBuilderStringBuffer,它们是不同的。第二个是线程安全的。
    猜你喜欢
    • 2014-07-15
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 2022-03-20
    • 2013-07-23
    相关资源
    最近更新 更多