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

Java 字串建構效能比較:String vs StringBuilder vs StringBuffer

     編輯:Java 相關知識

前言

字串操作是 Java 開發最高頻操作之一。String 不可變、StringBuilder 非線程安全、StringBuffer 線程安全,三者效能差異巨大。本文透過基準測試數據、原始碼分析、使用場景建議,幫助開發者做出正確選型。

效能排序 (由快到慢)

StringBuilder  >  StringBuffer  >  String

核心差異總覽

特性StringStringBuilderStringBuffer
可變性不可變可變可變
線程安全是 (不可變天然安全)否是 (synchronized)
繼承關係final classextends AbstractStringBuilderextends AbstractStringBuilder
Java 版本1.05.01.0
適用場景常量、少量拼接單線程大量拼接多線程共享拼接

原理深度解析

String 不可變的代價


String s = "a";
s += "b"; // 實際發生:
// 1. 建立 StringBuilder
// 2. append("a")
// 3. append("b")
// 4. toString() 產生新 String
// 5. 原 "a" 等待 GC

循環拼接 N 次會產生 N 個中間物件,時間複雜度 O(N²),記憶體壓力大。

StringBuilder / StringBuffer 共享底層實作

兩者皆繼承 AbstractStringBuilder,核心欄位:


char[] value;  // 字元陣列
int count;     // 實際長度

append() 直接在陣列尾端寫入,容量不足時擴容 (約 2倍 + 2),時間複雜度 O(N)。

StringBuffer 同步機制


public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

所有公共方法皆加 synchronized,多線程安全但效能損耗約 10-30%。

基準測試參考 (JMH, 100萬次 append)


@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class StringConcatBenchmark {
    @Benchmark
    public String stringConcat() {
        String s = "";
        for (int i = 0; i < 1_000_000; i++) s += "x";
        return s;
    }

    @Benchmark
    public String builderConcat() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1_000_000; i++) sb.append("x");
        return sb.toString();
    }

    @Benchmark
    public String bufferConcat() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 1_000_000; i++) sb.append("x");
        return sb.toString();
    }
}

典型結果

stringConcat    ~ 45,000 ms  (O(N²) 災難)
bufferConcat    ~   120 ms   (同步開銷)
builderConcat   ~    90 ms   (最快)

選型決策樹

  1. 是否多線程共享同一字串建構器?
    • 是 → StringBuffer
    • 否 → 進入第 2 步
  2. 是否大量拼接/迴圈建構?
    • 是 → StringBuilder
    • 否 → 進入第 3 步
  3. 簡單拼接、常量、參數傳遞
    • String (編譯器優化 + 常量池)

現代最佳實踐

  • Java 8+:單線程統一用 StringBuilder,多線程用 StringBuffer 或 ThreadLocal
  • 預估容量:new StringBuilder(1024) 減少擴容次數
  • 字串格式化:String.format() / StringBuilder.append() 替代複雜拼接
  • Stream API:list.stream().collect(Collectors.joining(",")) 簡潔高效
  • 避免 + 拼接:循環、大量拼接嚴禁使用 +

常見誤區

  1. 以為 StringBuffer 總是更好:單線程下同步純屬浪費
  2. 以為 String + 已優化:編譯器僅優化單行表達式,循環無效
  3. 忽略初始容量:預設 16 字元,大字串頻繁擴容複製陣列
  4. StringBuilder 當欄位共享:非線程安全,併發會導致資料錯亂或索引越界

總結

StringBuilder 是 95% 場景的正解。只有確定有多線程併發存取同一建構器時才用 StringBuffer。理解不可變與可變、同步與非同步的權衡,能寫出高效能、低 GC 壓力的 Java 程式碼。

參考資源

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