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

Java String 與 StringBuffer 差異深度解析與效能實測

     編輯:Java 程式設計入門

核心差異總覽

特性StringStringBufferStringBuilder
可變性不可變可變可變
執行緒安全天然安全同步化 (安全)非同步 (不安全)
繼承關係final classextends AbstractStringBuilderextends AbstractStringBuilder
記憶體行為每次修改建立新物件擴容機制 (預設 16 字元,滿時 2倍+2)同 StringBuffer
適用場景常量、少量拼接、多執行緒共享多執行緒大量字串操作單執行緒大量字串操作 (推薦)

底層機制深度解析

String 不可變性原理


// 反編譯視角
String a = "hello";
a += " world";
// 實際編譯為:
StringBuilder sb = new StringBuilder("hello");
sb.append(" world");
a = sb.toString();

每次拼接產生新 StringBuilder → append → toString() 新 String,舊物件等待 GC。

StringBuffer 擴容策略


// JDK 8 實作片段
public AbstractStringBuilder append(String str) {
    ensureCapacityInternal(count + str.length());
    // ...
}

private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value, newCapacity(minimumCapacity));
    }
}

private int newCapacity(int minCapacity) {
    return (value.length << 1) + 2; // 2倍 + 2
}

效能實測:10,000 次拼接


public class StringPerfTest {
    public static void main(String[] args) {
        int iterations = 10_000;

        // String +=
        long start = System.currentTimeMillis();
        String s = "";
        for (int i = 0; i < iterations; i++) s += i;
        System.out.println("String += : " + (System.currentTimeMillis() - start) + " ms");

        // StringBuffer
        start = System.currentTimeMillis();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < iterations; i++) sb.append(i);
        System.out.println("StringBuffer: " + (System.currentTimeMillis() - start) + " ms");

        // StringBuilder (單執行緒首選)
        start = System.currentTimeMillis();
        StringBuilder sbl = new StringBuilder();
        for (int i = 0; i < iterations; i++) sbl.append(i);
        System.out.println("StringBuilder: " + (System.currentTimeMillis() - start) + " ms");
    }
}

典型輸出結果

String += : 1,245 ms
StringBuffer: 2 ms
StringBuilder: 1 ms

關鍵方法差異

操作StringStringBuffer/Builder
追加concat() / +append()
插入無insert(index, str)
刪除無delete(start, end)
反轉無reverse()
查詢包含contains() ✓indexOf() ≠ -1
轉字串本身toString()

實務最佳實踐指南

✅ 推薦做法

  1. 單執行緒大量拼接:StringBuilder (JDK 5+ 首選)
  2. 多執行緒共享緩衝區:StringBuffer
  3. 固定格式化:String.format()、MessageFormat
  4. 集合轉字串:String.join() (JDK 8+)、Collectors.joining()
  5. 編譯期常量:直接用 +,編譯器優化為單一字串

❌ 避免做法

  • 迴圈中使用 String +=
  • 頻繁 substring() 大字串 (JDK 7+ 已修復共享 char[] 問題,但仍建議謹慎)
  • 不必要的 new String("literal")

進階:預估容量避免擴容


// 預估最終長度約 50,000 字元
StringBuilder sb = new StringBuilder(50_000);
for (int i = 0; i < 10_000; i++) {
    sb.append("Item").append(i).append(';');
}

預分配容量可消除擴容複製開銷,效能再提升 10-20%。

總結

String 不可變是設計而非缺陷,保證執行緒安全、字串常量池共享、安全性敏感場景不可篡改。StringBuilder 是單執行緒字串操作的標準選擇,StringBuffer 保留給少數多執行緒共享緩衝區場景。理解底層 char[]/byte[] (JDK 9+ Compact Strings) 擴容機制,預估容量、選對工具,才能寫出高效能 Java 程式碼。

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