StringBuilder和StringBuffer的区别

1734

StringBufferStringBuilder的主要区别是什么?在决定使用其中任何一个时是否存在性能问题?

33个回答

23

StringBuilder不是线程安全的。StringBuffer是线程安全的。更多信息在这里

编辑:至于性能,在hotspot启动后,StringBuilder是获胜者。然而,对于小迭代,性能差异可以忽略不计。


21

StringBuilderStringBuffer几乎相同,唯一的区别是StringBuffer是同步的,而StringBuilder不是。虽然StringBuilderStringBuffer更快,但性能差异非常小。 StringBuilder是SUN公司替代StringBuffer的产品,它在所有公共方法中避免了同步。除此之外,它们的功能是相同的。

良好使用示例:

如果您的文本将要更改并被多个线程使用,则最好使用StringBuffer。如果您的文本将要更改,但仅由单个线程使用,请使用StringBuilder


20

String 是不可变的。

StringBuffer 是可变的且同步的。

StringBuilder 也是可变的但它不是同步的。


另外,StringBuffer会锁定线程以访问这个线程安全的数据,因此操作速度较慢。StringBuilder不会锁定线程,并且以多线程方式运行,因此速度很快。当您不需要连接字符串时,使用String是一个好方法,但当您需要连接字符串时,请使用StringBuilder->因为String会在堆中每次创建新对象,而StringBuilder会返回相同的对象... - Musa

13

StringBuffer和StringBuilder的区别

来源:

enter image description here


11

javadoc解释了它们之间的区别:

该类提供与StringBuffer兼容的API,但不能保证同步。该类旨在用作StringBuffer的替代品,在只有一个线程使用字符串缓冲区的情况下(通常是这种情况),可以将其放置在原来StringBuffer的位置。如果可能的话,建议优先使用该类而不是StringBuffer,因为在大多数实现下它将更快。


10

StringBuilder(在Java 5中引入)与StringBuffer完全相同,除了其方法未同步。这意味着它比后者更具性能优势,但缺点是它不是线程安全的。

阅读教程以获取更多详细信息。


7
一个简单的程序,演示了StringBuffer和StringBuilder之间的区别:
/**
 * Run this program a couple of times. We see that the StringBuilder does not
 * give us reliable results because its methods are not thread-safe as compared
 * to StringBuffer.
 * 
 * For example, the single append in StringBuffer is thread-safe, i.e.
 * only one thread can call append() at any time and would finish writing
 * back to memory one at a time. In contrast, the append() in the StringBuilder 
 * class can be called concurrently by many threads, so the final size of the 
 * StringBuilder is sometimes less than expected.
 * 
 */
public class StringBufferVSStringBuilder {

    public static void main(String[] args) throws InterruptedException {

        int n = 10; 

        //*************************String Builder Test*******************************//
        StringBuilder sb = new StringBuilder();
        StringBuilderTest[] builderThreads = new StringBuilderTest[n];
        for (int i = 0; i < n; i++) {
            builderThreads[i] = new StringBuilderTest(sb);
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].join();
        }
        System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());

        //*************************String Buffer Test*******************************//

        StringBuffer sb2 = new StringBuffer();
        StringBufferTest[] bufferThreads = new StringBufferTest[n];
        for (int i = 0; i < n; i++) {
            bufferThreads[i] = new StringBufferTest(sb2);
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].join();
        }
        System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());

    }

}

// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {

    StringBuilder sb;

    public StringBuilderTest (StringBuilder sb) {
        this.sb = sb;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb.append("A");
        }

    }
}


//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {

    StringBuffer sb2;

    public StringBufferTest (StringBuffer sb2) {
        this.sb2 = sb2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb2.append("A");
        }

    }
}

5

建议使用StringBuilder,因为它不会进行同步操作,因此性能更好。 StringBuilder是旧的StringBuffer替代品


3
当然,除非你的应用程序是多线程的。 :) - Mark McKenna
3
@Mark 确实,但大多数情况下 StringBu(ff|ild)er 都是局部变量,只被单个线程使用。 - gabuzo
1
@MarkMcKenna:即使在多线程应用程序中,人们通常要么使用外部锁定,要么进行额外的工作以避免它。例如,如果两个线程都希望将包含多个字符串的记录追加到stringbuilder中,则它们必须聚合要添加的数据,然后将其作为一个单元添加,即使在不存在线程问题的情况下,执行一系列离散的追加操作会更快。 - supercat

4

字符串构建器

int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.

字符串缓冲区

StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);  

建议在可能的情况下使用StringBuilder,因为它比StringBuffer更快。但是,如果需要线程安全,则最好选择StringBuffer对象。


如果您需要线程安全,最好的选择是使用StringBuilder,因为StringBuffer仅对单个操作进行线程安全。对于多个操作,您需要显式锁定。 - Peter Lawrey

4

StringBuffer:

  • 多线程
  • 同步
  • 比StringBuilder慢

StringBuilder:

  • 单线程
  • 非同步
  • 比任何字符串都快

2
更准确地说,String c = a + b 等同于 String c = new StringBuilder().append(a).append(b).toString(),所以它并不更快。只是每次字符串赋值时都会创建一个新的字符串对象,而你本可以只有一个 (String d = a + b; d = d + c; 等同于 String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString(); 可以节省一个 StringBuilder 实例化)。 - Chop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接