为什么StringBuilder比String快得多

时间:2014-03-16 16:00:17

标签: java string stringbuilder

我知道这里发布了很多类似的问题,但这些问题并没有真正回答我的问题。

我只是想知道为什么StringBuilder比使用+运算符的字符串连接快得多。尽管+运算符内部是使用StringBufferStringBuilder实现的?

public void shortConcatenation(){
    long startTime = System.currentTimeMillis();
    while (System.currentTimeMillis()-startTime<=1000){


        character+="Y";

    }

    System.out.println("short :"+character.length());
}

////使用String builder

 public void shortConcatenation2(){
    long startTime = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    while (System.currentTimeMillis()-startTime<=1000){

        sb.append("Y");
    }
    System.out.println("string builder short :"+sb.length());
}

提前致谢!

3 个答案:

答案 0 :(得分:9)

你了解它的内部运作方式吗?

每次执行stringA += stringB;时,都会创建一个新字符串,并将其分配给stringA,这样它将消耗内存(新字符串实例!)和时间(复制旧字符串+另一个字符串的新字符)。

StringBuilder将在内部使用一组字符,当您使用.append()方法时,它会执行以下操作:

  • 检查字符串是否有任何可用空间追加
  • 再次进行一些内部检查并运行System.arraycopy来复制数组中字符串的字符。

就我个人而言,我认为每次分配一个新字符串(创建一个新的字符串实例,放置字符串等)在内存和速度方面可能非常广泛(特别是在/等等时)。 / p>

在您的示例中,使用StringBuilder更好,但如果您需要(示例)简单的内容,例如.toString()

public String toString() {
    return StringA + " - " + StringB;
}

没有区别(好吧,在这种情况下,你最好避免使用StringBuilder开销,这在这里没用。)

答案 1 :(得分:5)

java中的字符串是不可变的。这意味着对字符串进行操作的方法不能更改字符串的值。使用+ =进行字符串连接的工作原理是为一个全新的字符串分配内存,该字符串是前两个字符串的串联,并用这个新字符串替换引用。每个新的连接都需要构造一个全新的String对象。

相反,StringBuilder和StringBuffer类是作为可变字符序列实现的。这意味着当您将新的字符串或字符附加到StringBuilder时,它只是更新其内部数组以反映您所做的更改。这意味着只有当字符串超过StringBuilder中已存在的缓冲区时才会分配新内存。

答案 2 :(得分:0)

我可以列出一个非常好的示例来理解相同的内容(我是说我觉得这是一个很好的示例),请检查此处来自leetcode的代码问题:https://leetcode.com/problems/remove-outermost-parentheses/ 1:使用字符串 public String removeOuterParentheses(String S){

    String a="";
    int num=0;
    for(int i=0;i<S.length()-1;i++) {
     if(S.charAt(i)=='(' && num++>0) {
         a+="(";

     } 
        if(S.charAt(i)==')' && num-->1) {
         a+=")";

     } 

    }
  return a;  
}

,现在,使用StringBuilder。 public String removeOuterParentheses(String S){

    StringBuilder sb = new StringBuilder();


    int a=0;
    for(char ch : S.toCharArray()) {
        if(ch=='(' && a++>0) sb.append('(');
        if(ch==')' && a-->1) sb.append(')');
    }

    return sb.toString();

}

两者的表现差异很大, 第一个提交使用String,而第二个提交使用StringBuilder。

enter image description here 如上所述,理论是相同的。按属性的字符串是不可变且同步的,即其状态无法更改。第二个。由于每当使用串联函数或“ +”时都会创建新的内存分配,因此开销很大。它会消耗大量的堆,并且会变慢。相比之下,StringBuilder是可变的,它只会追加并不会在消耗的内存上创建过载。

希望这会有所帮助。