整理 Effective Java 書中 Item 63: Beware the performance of string concatenation 心得筆記

主旨

+ 來拼接字串雖然寫起來很直覺,但如果在迴圈中反覆拼接字串,會造成 效能災難

字串是 immutable 的,每次用 + 拼接,背後其實都在重新建立新物件。這會讓原本應該是線性時間的操作,變成 O(n²) 的低效實作。

範例:錯誤的字串串接方式

來看一個帳單輸出的方法:

// 效能超差的寫法
public String statement() {
    String result = "";
    for (int i = 0; i < numItems(); i++) {
        result += lineForItem(i); // 每次都產生新字串
    }
    return result;
}

這段程式碼在少量資料時還看不出問題,但如果 numItems() 回傳的是 1000、10000…
這程式會越來越慢,因為每次都要把前面的字串重新複製一遍。


正確做法:使用 StringBuilder

// ✅ 高效能的字串串接方式
public String statement() {
    StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);
    for (int i = 0; i < numItems(); i++) {
        b.append(lineForItem(i));
    }
    return b.toString();
}

這段使用 StringBuilder

  • 不會每次建立新字串
  • 串接過程只在原有記憶體中追加
  • 可預先設定容量(省去擴充成本)

效能測試:

  • numItems = 100 時,使用 StringBuilder 的版本大約 快了 6.5 倍
  • 數量越多,差異越大,因為一個是 O(n²),一個是 O(n)

真實世界經驗補充

即使在 Java 9 之後,編譯器會自動幫你用 StringBuilder 優化像這樣的語法:

String s = "Hello" + name + "!";

但如果你是在 迴圈中不斷使用 +=,這種優化仍然不夠用。請改用 StringBuilder


小結:字串拼接的黃金守則

敘述建議做法
少量字串拼接(2~3 個)+ OK
多次拼接或迴圈內操作使用 StringBuilder
已知總長度可預估(如每行 80 字、100 筆)預先設定 StringBuilder 容量
字串拼接效能很重要不要用 +,用 StringBuilder