【问题标题】:Advantage of String over StringBuilder in Java [duplicate]Java中String优于StringBuilder的优势[重复]
【发布时间】:2017-05-04 07:25:51
【问题描述】:

为什么有人会使用String 而不是StringBuilder。

我知道以下事实:

  • StringBuilder 相对于 String 的优势,
  • 字符串是不可变的,
  • 我们可以用 StringBuilder 做任何事情,甚至更多。
  • 也不能说 String 更快,因为两者都是非同步的。

如果StringBuilder 已经存在,为什么有人会使用String?

【问题讨论】:

  • 据我所知,串联在 String 中的成本很高,因为它会创建一个新对象。因此,这是 StringBuilder 的一个优势。
  • 就像在之前的评论中指出的那样,链接到another thread,字符串连接通常被编译为在内部使用 StringBuilder。
  • 运行以下代码可以看到一个区别:'long s = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i
  • 我知道 StringBUilder 优于 String,我想知道为什么 String 优于 StringBuilder?
  • @KlitosKyriacou 您不必必须调用 toString() 来比较内容,最快的方法是遍历(参见我的示例)。但是,是的,它的效率仍然低得多。

标签: java string


【解决方案1】:

StringBuilder 是可变的,而 String 是不可变的。不可变意味着它不会改变,所以你关于它不同步的观点是没有意义的 - 没有可能要同步的变化。

简而言之,如果您不需要 StringBuilders 的额外功能(这在字符串中很常见),那么 String 的效率会更高。它还在 JVM 中具有 Java 中其他对象所没有的高度优化的特殊处理。

字符串特定优化的最显着示例,字符串池,它使字符串表现得像常量,因为同一个实例可以在整个应用程序中自动共享,从而节省内存和时间。对于其他对象,这不会自动实现,对于可变对象,通常甚至不需要。与定制池相比,字符串池已显示允许more objects with better performance。为了提高性能而只使用一个字符串实例的过程称为string interning。

由于您只使用一个实例,因此在比较时,您只需比较参考。对于每个 StringBuilder 实例,您需要评估对象的内容才能做到这一点。 Stringbuilder uses an Array as a backing object 并且必须遍历该 Array 以获取其内容,这相当昂贵。这假设您对字符串内容而不是对象实例感兴趣,String/StringBuilder/StringBuffer 几乎总是如此。


String 和 StringBuilder 内容的简单性能测试比较:

public class CompTest {

  // fastest way to compare StringBuilder contents according to
  // http://stackoverflow.com/questions/11007387/what-is-an-efficient-way-to-compare-stringbuilder-objects
  static boolean contentEquals(StringBuilder sb1, StringBuilder sb2) {
    if (sb1.length() != sb2.length()) return false;
    for (int i = 0, len = sb1.length(); i < len; i++) {
      if (sb1.charAt(i) != sb2.charAt(i)) return false;
    }
    return true;
  }

  public static void main(String args[]) {

    StringBuilder fooSb = new StringBuilder("foo");
    StringBuilder barSb = new StringBuilder("foo");
    String foo = "foo";
    String bar = "foo";

    System.out.println(foo.equals(bar));
         // returns true
    System.out.println(fooSb.equals(barSb));
         // returns false, so cannot be used to check contents
    System.out.println(contentEquals(fooSb,barSb));
         // returns true

    long time;

    time = System.currentTimeMillis();
    for (int i = 0; i < 2000000000; i++) {
      if (foo.equals(bar)) continue;
    }
    System.out.println("str comparisons took " + (System.currentTimeMillis() - time) + " ms");

    time = System.currentTimeMillis();
    for (int i = 0; i < 2000000000; i++) {
      if (contentEquals(fooSb,barSb)) continue;
    }
    System.out.println("sb comparisons took " + (System.currentTimeMillis() - time) + " ms");

    /* repeat the test as we know JVM is warmed up by now */

    time = System.currentTimeMillis();
    for (int i = 0; i < 2000000000; i++) {
      if (foo.equals(bar)) continue;
    }
    System.out.println("str comparisons took " + (System.currentTimeMillis() - time) + " ms");

    time = System.currentTimeMillis();
    for (int i = 0; i < 2000000000; i++) {
      if (contentEquals(fooSb,barSb)) continue;
    }
    System.out.println("sb comparisons took " + (System.currentTimeMillis() - time) + " ms");

 }
}

有结果:

true
false
true
str comparisons took 1244 ms
sb comparisons took 11530 ms
str comparisons took 1231 ms
sb comparisons took 12098 ms

【讨论】:

  • 我之所以这么说是因为如果你检查 StringBuilder 和 StringBuffer,你会发现唯一的区别是性能,因为 StringBuffer 的方法是同步的,并且需要更多的时间来执行。在这里我提出这个事实是因为我知道 String 和 StringBuilder 都是非同步的,因此这不能成为使用 String 而不是 StringBuilder 的理由。
  • String在什么方面比StringBuilder效率更高,能解释一下吗?
  • @AzamKhan 你是对的。我测试过StringBuilder vs String,StringBuilder比String快很多。
  • @BahramdunAdil 您只测试了字符串连接,这与我的回答无关。
  • @BahramdunAdil StringBuilder 在某些情况下比String 快,并非在所有情况下。
猜你喜欢
  • 2010-11-15
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
  • 2015-04-02
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
相关资源
最近更新 更多