String vs StringBuffer vs StringBuilder

String是Java中最常用的类之一。StringBuffer和StringBuilder类提供了操作字符串的方法。我们将研究StringBuffer和StringBuilder之间的区别。StringBuffer vs StringBuilder是一个常见的Java面试问题。

String vs StringBuffer vs StringBuilder

字符串是核心Java面试中最重要的主题之一。如果你正在编写一个在控制台上打印输出的程序,你会使用String。本教程旨在重点介绍String类的主要特性。然后我们将比较StringBuffer和StringBuilder类。

Java中的字符串

  1. String类表示字符串,我们可以用两种方式实例化String。

    String str = "ABC";
    // 或者
    String str = new String("ABC");
    
  2. String在Java中是不可变的。因此,在多线程环境中使用它是合适的。我们可以在函数之间共享它,因为不会出现数据不一致的问题。

  3. 當我們使用雙引號創建一個字串時,JVM首先在字符串池中尋找具有相同值的字串。如果找到,則返回字符串對象在池中的引用。否則,它在字符串池中創建一個新的字串對象並返回引用。JVM通過在不同線程中使用相同的字串來節省大量內存。

  4. 如果使用new運算符創建字串,它將在堆內存中創建。

  5. +運算符對於字串是重載的。我們可以使用它來連接兩個字串。儘管在內部它使用StringBuffer來執行此操作。

  6. 字串覆寫equals() 和 hashCode()方法。兩個字串僅在它們具有相同的字元序列時才相等。equals()方法是區分大小寫的。如果您要進行不區分大小寫的檢查,應使用equalsIgnoreCase()方法。

  7. 字串使用 UTF-16 編碼進行字元流。

  8. 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

  1. 字串是不可變的,而StringBuffer和StringBuilder是可變的類別。
  2. StringBuffer是線程安全且同步的,而StringBuilder則不是。這就是為什麼StringBuilder比StringBuffer更快的原因。
  3. 字串連接運算子(+)內部使用StringBuffer或StringBuilder類別。
  4. 在非多線程環境中進行字串操作時,我們應該使用StringBuilder,否則使用StringBuffer類別。

這就是有關字串、StringBuffer和StringBuilder之間差異的快速總結。在大多數一般編程情境中,StringBuilder比StringBuffer更適用。參考:

Source:
https://www.digitalocean.com/community/tutorials/string-vs-stringbuffer-vs-stringbuilder