首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 字串拼接效能大比拼:+、concat、StringBuilder 與 StringBuffer

     編輯:Java 相關知識

為什麼 + 在迴圈裡會慢到爆?

String 為不可變物件。s += "*" 實際上每次都會:

  1. 建立新 StringBuilder(或舊版 StringBuffer)。
  2. append 原字串。
  3. append 新片段。
  4. toString() 產生新 String。
  5. 舊字串成為垃圾等待 GC。

50,000 次迴圈 = 50,000 個中間物件,記憶體壓力大、GC 頻繁、效能指數級下降。

實測環境與方法

  • OS:Win 7 64-bit,JVM 32-bit 7-ea,4GB RAM,雙核 2.0 GHz。
  • 工具:Perf4J(統計最小/最大/平均/標準差)。
  • 場景:20 次外層迴圈 × 50,000 內層迴圈拼接 "*"。
  • 四種方式:+、concat()、StringBuffer.append()、StringBuilder.append()。

關鍵發現(修正原文測試碼錯誤後)

方式平均耗時 (ms)備註
StringBuilder~1.8非同步、無鎖,單執行緒首選
StringBuffer~2.0同步(鎖),多執行緒安全但較慢
String.concat()~3.3內部同樣用 StringBuilder,但每次新建實例 + toString()
+ (迴圈)~1650+每次新建 Builder,極度低效

位元組碼證據:concat() 內部其實也是 StringBuilder

new StringBuilder()        // 1. 新建
dup
invokespecial StringBuilder.
aload_1                    // 載入原字串
invokevirtual StringBuilder.append(String)
ldc "*"                    // 載入常數
invokevirtual StringBuilder.append(String)
invokevirtual StringBuilder.toString() // 2. 轉回 String
astore_1                   // 存回變數

可見 concat() 每次呼叫都 新建 StringBuilder → append 兩次 → toString,比直接重用同一個 StringBuilder 多出物件建立與方法呼叫開銷。

最佳實踐建議

  1. 單執行緒、大量拼接: 直接用 StringBuilder sb = new StringBuilder(); sb.append(...); 重用實例。
  2. 多執行緒共享緩衝區: 用 StringBuffer(或 ThreadLocal 避免鎖)。
  3. 簡單少量拼接(非迴圈): + 或 concat() 皆可,編譯器會優化成 StringBuilder,可讀性優先。
  4. Java 8+ String.join() / Collectors.joining(): 串流/集合拼接更優雅。

補充:編譯器優化

String s = "a" + "b" + "c"; // 編譯期常數折疊 → "abc"
String s = a + b + c;       // 執行期 → new StringBuilder().append(a).append(b).append(c).toString()

所以迴圈外的 + 沒有效能問題,問題在於迴圈內重複建立 Builder。

結論

效能排序:StringBuilder > StringBuffer > concat() >> 迴圈內 +。
養成習慣:需要拼接時預設用 StringBuilder,除非確定多執行緒共享才用 StringBuffer,絕不在迴圈裡寫 s += ...。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved