Java 中的 String 與 StringBuffer 比較
1. 概述
String
和StringBuffer
是在 Java 中處理字串時使用的兩個重要類別。簡單來說,字串就是字元序列。例如“java”、“spring”等。
String
和StringBuffer
之間的主要區別在於String
是不可變的,而StringBuffer
是可變的且線程安全的。
在本教程中,我們將比較String
和StringBuffer
類,並了解兩者之間的異同。
2. String
String
類別表示字串。 Java 將所有字串文字(例如「baeldung」)實作為此類別的實例。
讓我們創建一個String
文字:
String str = "baeldung";
我們也建立一個String
物件:
Char data[] = {'b', 'a', 'e', 'l', 'd', 'u', 'n', 'g'};
String str = new String(data);
我們也可以執行以下操作:
String str = new String(“baeldung”);
字串是常數且不可變的,因此可以共用。
2.1.字串文字與字串對象
String
文字是不可變的字串,儲存在堆記憶體中稱為字串池的特殊記憶體空間。 Java 不會為具有相同值的字串文字指派新的記憶體空間。相反,它使用字串駐留。
相反,JVM 在字串池之外的堆中為新建立的 String 物件分配單獨的記憶體。
因此,每個字串物件引用不同的記憶體位址,即使兩者可能具有相同的值。請注意, String
文字仍然是String
物件。然而,反之則不然。
2.2.字串池
字串文字儲存在稱為字串池的 Java 堆的保留記憶體區域中。
2.3.弦樂實習
字串駐留是編譯器用來避免冗餘記憶體分配的最佳化技術。如果已經存在類似的值,它會避免為新的字串文字分配記憶體。相反,它適用於現有副本:
String
的常見動作包括連線、比較和搜尋。 Java 語言也為字串連接運算子 (+) 以及其他物件到字串的轉換提供特殊支援。值得注意的是, String
內部使用StringBuffer
及其append方法來執行連線:
String str = "String";
str = str.concat("Buffer");
assertThat(str).isEqualTo("StringBuffer");
assertThat(str.indexOf("Buffer")).isEqualTo(6);
3. StringBuffer
StringBuffer
是一個字元序列,就像String
一樣。然而,與String
不同,它是可變的。我們可以透過諸如append()
和insert()
之類的方法呼叫來修改StringBuffer
。 append
方法將字元序列新增至StringBuffer,
而insert
方法則在指定索引處插入字元序列。 StringBuffer
類別有兩個重載方法來處理任何物件。在附加或插入StringBuffer
之前,該物件將轉換為其字串表示形式:
StringBuffer sBuf = new StringBuffer("String");
sBuf.append("Buffer");
assertThat(sBuf).isEqualToIgnoringCase("StringBuffer");
sBuf.insert(0, "String vs ");
assertThat(sBuf).isEqualToIgnoringCase("String vs StringBuffer");
StringBuffer
是線程安全的,可以工作在多線程環境中。同步**可確保所有語句的執行順序正確並避免資料爭用狀況**。
Java 1.5 引入了StringBuilder
作為StringBuffer
的替代品。
4. 效能比較
String
和StringBuffer
具有相似的效能。但是,使用StringBuffer
進行字串操作比使用String
更快,因為String
每次都需要建立一個新對象,並且所有變更都發生在新String
上,導致更多的時間和記憶體消耗。
讓我們用 JMH 做一個快速的微基準測試來比較String
和StringBuffer
的串聯性能:
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Measurement(batchSize = 100000, iterations = 10)
@Warmup(batchSize = 100000, iterations = 10)
@State(Scope.Thread)
public class ComparePerformance {
String strInitial = "springframework";
String strFinal = "";
String replacement = "java-";
@Benchmark
public String benchmarkStringConcatenation() {
strFinal = "";
strFinal += strInitial;
return strFinal;
}
@Benchmark
public StringBuffer benchmarkStringBufferConcatenation() {
StringBuffer stringBuffer = new StringBuffer(strFinal);
stringBuffer.append(strInitial);
return stringBuffer;
}
}
Benchmark Mode Cnt Score Error Units
ComparePerformance.benchmarkStringBufferConcatenation ss 10 16.047 ± 11.757 ms/op
ComparePerformance.benchmarkStringConcatenation ss 10 3.492 ± 1.309 ms/op
5. 對照表
總結一下差異:
String | StringBuffer |
String 是字元序列且是不可變的 | StringBuffer 類似於String 但可以修改,即它是可變的 |
由於其不變性,可以輕鬆共享 | 它只能在同步線程之間共享 |
修改需要建立新字串 | 修改需要呼叫某些方法 |
修改速度慢 | 修改速度更快 |
它使用字串池來存儲數據 | 它使用堆疊記憶體 |
六,結論
在本文中,我們比較了String
和StringBuffer
類別。與往常一樣,範例程式碼可以在 GitHub 上取得。