【问题标题】:Does "+" use in String concatenation affect efficiency? [duplicate]字符串连接中使用“+”会影响效率吗? [复制]
【发布时间】:2011-10-19 03:26:20
【问题描述】:

我曾在 java 中使用过 String、StringBuilder 和 StringBuffer。
我在从效率的角度思考的时候想到了这个问题。

字符串连接中使用“+”会影响效率吗?

【问题讨论】:

  • 我认为这在 SO 上已经讨论了很多?
  • 是的,我认为规则是,如果您要连接两个以上的字符串,则应该使用 stringbuilder ......如果您提前有想法/答案,(1)把它在问题中作为额外信息或 (b) 不要问您已经知道答案的问题。

标签: java string performance stringbuffer


【解决方案1】:

是的,但在大多数情况下,它应该无关紧要。

对字符串常量使用“+”是最有效的,因为编译器可以执行连接。

如果您要连接两个字符串,concat 方法是最有效的,因为它避免使用 StringBuilder。

除了向后兼容性之外,几乎没有使用 StringBuffer 的好理由。 StringBuilder 或 StringWriter 是更好的选择。但是,它仍然比 JDK 中的 StringBuilder 更频繁地显式使用:P

StringBuffer is dead, long live StringBuffer

【讨论】:

  • "so little" 在小连接的情况下。但是,我有处理具有许多连接(解析器/过滤器)的类的经验,其中简单地从连接更改为缓冲区附加将(非常慢的)执行时间减半。微基准也不太可能向您显示添加所有这些额外的中间字符串对象的垃圾收集成本,但它们会在您的应用程序的生命周期内分摊。
  • 在我的应用程序中,我使用线程本地 ByteBuffer 并使用不创建任何对象的方法直接从该线程读取/写入。对于 99% 的用例来说,这非常极端,但它可以让您的登录时间缩短到几微秒。 ;)
【解决方案2】:

如果您在单个语句中进行连接,那么这无关紧要,因为编译器/JIT 编译器会使用 StringBuilder 自动优化它。

所以"a"+b+"c" 将被优化为(new StringBuilder("a").append(b).append("c")).toString()

但是,如果您在一个循环中连接大量 Strings,请务必明确使用 StringBuilder,因为它会显着加快您的程序。

String a = "";

for( int i = 0; i < 1000000; i++ )
    a += i;

应该改为

StringBuilder sb = new StringBuilder();

for( int i = 0; i < 1000000; i++ )
    sb.append(i);

String a = sb.toString();

【讨论】:

    【解决方案3】:

    有点同意,但仍然

    来自 JLS,15.18.1.2

    字符串拼接的优化

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

    对于原始类型,实现还可以通过直接从原始类型转换为字符串来优化包装对象的创建。

    【讨论】:

      【解决方案4】:

      在你的例子中:

      " Does +" + " use in String concatenation affect efficiency? "
      

      我们必须文字字符串,它可能会被编译器替换,所以这会比 StringBuffer/append/toString 更快。

      但与什么相比更高效/更快?代码执行?代码编写?读码?

      自从看了一篇

      "Foo = " + foo;
      

      非常简单,我会推荐它,只要它不重复一百万次,或者 "s += s2;"重复了一百次。

      特别是,

      System.out.println ("Player " + n + " scores " + player[n].score); 
      

      更易读
      System.out.println (new StringBuffer ("Player ").append ((Integer.valueOf (n)).toString ().append (" scores ").append (...
      

      在需要高性能的应用程序中避免它,或者连接大量字符串,或者大量递归。

      【讨论】:

      • 好吧,说句公道话,真的是new StringBuffer ("Player ").append(n).append (" scores ").append(player[n].score)。但是你的观点仍然有效,即使你的例子是虚伪的。
      【解决方案5】:

      如果您使用 '+' 进行多次串联,那么在某种程度上是肯定的。考兹 当您执行 String a + String b 时,它实际上在内部创建了一个 StringBuffer 对象并使用 StringBuffer 的 append()。因此,每次执行“+”时,都会创建一个新的临时 StringBuffer 对象,用“a”初始化,然后附加“b”,然后将其转换为字符串对象。

      因此,如果您需要多个连接,您应该创建一个 StringBuffer(线程安全)/StringBuilder(非线程安全)对象并继续追加,这样您就可以避免一次又一次地创建 StringBuffer 对象。

      【讨论】:

      • 只有在多个语句中展开字符串时,“multiple”才是正确的。带有 + 的单个语句与单个 stringbuilder 一样有效,但更易于阅读(并且编译器可以更好地优化初始大小)。
      • 我很确定第二段解决了这个问题。
      猜你喜欢
      • 2013-06-18
      • 1970-01-01
      • 2012-02-02
      • 1970-01-01
      • 2020-01-21
      • 2011-05-23
      • 1970-01-01
      • 2012-07-01
      • 2013-11-22
      相关资源
      最近更新 更多