String是Java中最常用的类之一。StringBuffer和StringBuilder类提供了操作字符串的方法。我们将研究StringBuffer和StringBuilder之间的区别。StringBuffer vs StringBuilder是一个常见的Java面试问题。
String vs StringBuffer vs StringBuilder
字符串是核心Java面试中最重要的主题之一。如果你正在编写一个在控制台上打印输出的程序,你会使用String。本教程旨在重点介绍String类的主要特性。然后我们将比较StringBuffer和StringBuilder类。
Java中的字符串
-
String类表示字符串,我们可以用两种方式实例化String。
String str = "ABC"; // 或者 String str = new String("ABC");
-
String在Java中是不可变的。因此,在多线程环境中使用它是合适的。我们可以在函数之间共享它,因为不会出现数据不一致的问题。
-
當我們使用雙引號創建一個字串時,JVM首先在字符串池中尋找具有相同值的字串。如果找到,則返回字符串對象在池中的引用。否則,它在字符串池中創建一個新的字串對象並返回引用。JVM通過在不同線程中使用相同的字串來節省大量內存。
-
如果使用new運算符創建字串,它將在堆內存中創建。
-
+運算符對於字串是重載的。我們可以使用它來連接兩個字串。儘管在內部它使用StringBuffer來執行此操作。
-
字串覆寫equals() 和 hashCode()方法。兩個字串僅在它們具有相同的字元序列時才相等。equals()方法是區分大小寫的。如果您要進行不區分大小寫的檢查,應使用equalsIgnoreCase()方法。
-
字串使用 UTF-16 編碼進行字元流。
-
String 是一個 final 類別。所有欄位都是 final,除了“private int hash”。此欄位包含 hashCode() 函數的值。僅在第一次調用 hashCode() 方法時才計算哈希碼值,然後將其快取在此欄位中。此外,哈希是使用 String 類別的 final 欄位進行一些計算而生成的。因此,每次調用 hashCode() 方法時,都會得到相同的輸出。對於調用者來說,似乎每次都在進行計算,但在內部它被快取在 hash 欄位中。
String vs StringBuffer
由於 String 在 Java 中是不可變的,當我們進行 String 操作,例如連接、子串等,它會生成一個新的 String,並且丟棄舊的 String 以便進行垃圾回收。這些操作很耗資源,會在堆中產生大量的垃圾。因此,Java 提供了 StringBuffer 和 StringBuilder 類別,應該用於 String 的操作。StringBuffer 和 StringBuilder 是可變的物件。它們提供了 append()、insert()、delete() 和 substring() 方法來操作 String。
StringBuffer vs StringBuilder
StringBuffer 在 Java 1.4 之前是字串操作的唯一選擇。但是,它有一個缺點,即其所有公共方法都是同步的。StringBuffer 提供了線程安全性,但代價是性能。在大多數情況下,我們不會在多線程環境中使用字串。因此,Java 1.5 引入了一個新的類別 StringBuilder,它與 StringBuffer 相似,除了線程安全性和同步性。StringBuffer 有一些額外的方法,如 substring、length、capacity、trimToSize 等。然而,這些都不是必需的,因為你在 String 中都有這些方法。這就是為什麼這些方法從未在 StringBuilder 類別中實現的原因。StringBuffer 在 Java 1.0 中引入,而 StringBuilder 類別則在 Java 1.5 中引入,是在查看了 StringBuffer 的缺點之後引入的。如果您在單線程環境中,或者不關心線程安全性,應該使用 StringBuilder。否則,對於線程安全操作,請使用 StringBuffer。
StringBuilder vs StringBuffer 效能
I am trying to check the effect on performance because of synchronization with a sample program that performs append()
on StringBuffer and StringBuilder object for multiple times.
package com.journaldev.java;
import java.util.GregorianCalendar;
public class TestString {
public static void main(String[] args) {
System.gc();
long start=new GregorianCalendar().getTimeInMillis();
long startMemory=Runtime.getRuntime().freeMemory();
StringBuffer sb = new StringBuffer();
//StringBuilder sb = new StringBuilder();
for(int i = 0; i<10000000; i++){
sb.append(":").append(i);
}
long end=new GregorianCalendar().getTimeInMillis();
long endMemory=Runtime.getRuntime().freeMemory();
System.out.println("Time Taken:"+(end-start));
System.out.println("Memory used:"+(startMemory-endMemory));
}
}
I ran the same code for the StringBuffer object also to check the time and memory values. I have executed the code 5 times for each case and then calculated the average values.
Value of i | StringBuffer (Time, Memory) | StringBuilder (Time, Memory) |
---|---|---|
10,00,000 | 808, 149356704 | 633, 149356704 |
1,00,00,000 | 7448, 147783888 | 6179, 147783888 |
很明顯,即使在單線程環境中,StringBuilder 的性能也比 StringBuffer 好。這種性能上的差異可能是由於 StringBuffer 方法中的同步造成的。
字串 vs StringBuffer vs StringBuilder
- 字串是不可變的,而StringBuffer和StringBuilder是可變的類別。
- StringBuffer是線程安全且同步的,而StringBuilder則不是。這就是為什麼StringBuilder比StringBuffer更快的原因。
- 字串連接運算子(+)內部使用StringBuffer或StringBuilder類別。
- 在非多線程環境中進行字串操作時,我們應該使用StringBuilder,否則使用StringBuffer類別。
這就是有關字串、StringBuffer和StringBuilder之間差異的快速總結。在大多數一般編程情境中,StringBuilder比StringBuffer更適用。參考:
Source:
https://www.digitalocean.com/community/tutorials/string-vs-stringbuffer-vs-stringbuilder