StringBuilders有什么好处?

时间:2011-11-02 02:20:42

标签: java

  

可能重复:
  StringBuilder vs String concatenation in toString() in Java

为什么StringBuilders比普通的String Concatenation更好用?

7 个答案:

答案 0 :(得分:8)

这些天的java编译器非常聪明,无论如何都会使用StringBuilder来连接字符串。

这使以下代码相同

System.out.println("test = "+test+" test2 = "+test2);
System.out.println((new StringBuilder()).append("test =  ").append(test).append("test2 = ").append(test2).toString());

因此,如果你的字符串落在一个可执行行上,你就不应该害怕使用字符串连接。

但是,如果你循环遍历一些东西并将字符串连接在一起,那么java运行时将创建所有这些新的StringBuilder,然后将它们连接在一起,因此在这种情况下提供你自己的StringBuilder单个实例更有效率< / p>

StringBuilder sb = new StringBuilder();
for(String test : testStrings) {
   sb.append(" ").appendtest);   
}

答案 1 :(得分:2)

因为字符串是不可变的。当您进行字符串连接时,您可以创建许多字符串作为临时值,然后必须进行垃圾回收。使用StringBuilder,有一个潜在的可变数据结构,所以你只需继续使用它。

效果是限制GC的数量并减少执行的JVM指令的数量。说明通常通常是个大问题,但我发现字符串连接的错误用法会将JVM推入大规模的GC加载。

答案 2 :(得分:1)

StringBuilder是可变的,因此您不会创建新的字符串。

答案 3 :(得分:1)

StringBuilder不会在连接,子串e.t.c等操作中在池中创建新的字符串。简而言之,每次对String进行操作时,都会在池中创建一个新的String。

String x = "abc"
x= x+"def";

因此在池中创建了三个字符串。 “abc”,“def”。 “abcdef”..... StringBUilder只使用一个对象时可以完成同样的任务。

建议使用StringBuilder而不是StringBuffer,因为StringBuffer是线程安全的并且具有同步方法,因此除非需要线程安全,否则建议使用stringbuilder,因为字符串缓冲区可能会导致性能开销,但可以忽略不计。

答案 4 :(得分:1)

我决定通过YourKit Java Profiler运行3个简单的测试用例,将您的问题提交到'profiler'测试。我使用String,StringBuilder和StringBuffer执行了三次测试。

每个的来源如下:

 public void testString() throws Exception {

    for ( int x = 0; x < 10000000; x++ ) {
        String s = "the quick brown fox jumped over the lazy dogs. ";
        for ( int i = 0 ; i < 5; i++ ) {
            s += s;
        }
    }
}
public void testStringBuilder() throws Exception {

    for ( int x = 0; x < 10000000; x++ ) {
        StringBuilder s = new StringBuilder("the quick brown fox jumped over the lazy dogs. ");
        for ( int i = 0 ; i < 5; i++ ) {
            s.append(s);
        }
    }
}

public void testStringBuffer() throws Exception {

    for ( int x = 0; x < 10000000; x++ ) {
        StringBuffer s = new StringBuffer("the quick brown fox jumped over the lazy dogs. ");
        for ( int i = 0 ; i < 5; i++ ) {
            s.append(s);
        }
    }
}

这些测试用例中的每一个都是在64位JDK1.6_27上启用“跟踪”的情况下执行的。以下是每次测试的时间结果(抱歉,由于SO限制而不得不删除图像,而是发布CSV输出)。

首先要注意的是,在String和StringBuffer测试中,JVM使用StrinbBuffers作为内部实现。但是,在String情况下,整体性能要差得多。差异的关键在于调用计数。

在String情况下,使用连接运算符(“+ =”)会导致创建两个StringBuffer实例(请参阅“调用计数”结果:99M对48M)。

因此,如果您要进行大量连接,请直接使用StringBuffer。

字符串:

"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testString()","190497","190497","0","1", "7"
"java.lang.StringBuilder.append(String)","117742","0","117742","99825142", "8"
"java.lang.StringBuilder.toString()","46142","0","46142","49912563", "8"
"java.lang.StringBuilder.<init>()","26612","0","26612","49912563", "8"

的StringBuilder:

"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testStringBuilder()","90179","90179","0","1", "7"
"java.lang.StringBuilder.append(CharSequence)","79212","0","79212","48924577", "8"
"java.lang.StringBuilder.<init>(String)","10966","0","10966","9784916", "8"

的StringBuffer:

"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testStringBuffer()","83518","83518","0","1", "7"
"java.lang.StringBuffer.append(StringBuffer)","73207","0","73207","48694049", "8"
"java.lang.StringBuffer.<init>(String)","10311","0","10311","9738810", "8"

答案 5 :(得分:0)

由于字符串是不可变的,如果要更改代码中的String,可能需要使用StringBuilder类。

答案 6 :(得分:0)

String是不可变的,因此每个concat都会创建一个新对象,Stringbuffer / builder是可变的。提供了一条说明at this link