StringBuilder

2020-08-14 21:08:15

Java編譯器對String做了特殊處理,使得我們可以直接用+拼接字串。

考察下面 下麪的回圈程式碼:

String s = "";
for (int i = 0; i < 10; i++) {
    s = s + "," + i;
}

在这里插入图片描述
雖然可以直接拼接字串,但是,在回圈中,每次回圈都會建立新的字串物件,然後扔掉舊的字串。這樣,絕大部分字串都是臨時物件,不但浪費記憶體,還會影響GC效率。

爲了能高效拼接字串,Java標準庫提供了StringBuilder,它是一個可變物件,可以預分配緩衝區,這樣,往StringBuilder中新增字元時,不會建立新的臨時物件:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
    sb.append(',');
    sb.append(i);
}
String s = sb.toString();

StringBuilder還可以進行鏈式操作:

public class test {
    public static void main(String srga[]){
        StringBuilder sb = new StringBuilder();
        sb.append("Mr ")
                .append("Bob")
                .append("!")
                .insert(0, "Hello, ");
        System.out.println(sb.toString());
    }
}

如果我們檢視StringBuilder的原始碼,可以發現,進行鏈式操作的關鍵是,定義的append()方法會返回this,這樣,就可以不斷呼叫自身的其他方法。

仿照StringBuilder,我們也可以設計支援鏈式操作的類。例如,一個可以不斷增加的計數器:

// 鏈式操作
public class Main {
    public static void main(String[] args) {
        Adder adder = new Adder();
        adder.add(3)
             .add(5)
             .inc()
             .add(10);
        System.out.println(adder.value());
    }
}

class Adder {
    private int sum = 0;

    public Adder add(int n) {
        sum += n;
        return this;
    }

    public Adder inc() {
        sum ++;
        return this;
    }

    public int value() {
        return sum;
    }
}

注意:對於普通的字串+操作,並不需要我們將其改寫爲StringBuilder,因爲Java編譯器在編譯時就自動把多個連續的+操作編碼爲StringConcatFactory的操作。在執行期,StringConcatFactory會自動把字串連線操作優化爲陣列複製或者StringBuilder操作。

你可能還聽說過StringBuffer,這是Java早期的一個StringBuilder的執行緒安全版本,它通過同步來保證多個執行緒操作StringBuffer也是安全的,但是同步會帶來執行速度的下降。

StringBuilder和StringBuffer介面完全相同,現在完全沒有必要使用StringBuffer。

小結

  • StringBuilder是可變物件,用來高效拼接字串;

  • StringBuilder可以支援鏈式操作,實現鏈式操作的關鍵是返回範例本身;

  • StringBuffer是StringBuilder的執行緒安全版本,現在很少使用。

參考文獻

  • https://www.liaoxuefeng.com/wiki/1252599548343744/1260471862687712