String,StringBuffer與StringBuilder的區別

1. 三者區別


String 字符串常量

StringBuffer 字符串變量(線程安全)

StringBuilder 字符串變量(非線程安全)


String類

String類常用方法


1.1 String

簡要的說, String 類型和 StringBuffer 類型的主要性能區別其實在於 String 是不可變的對象, 因此在每次對 String 類型進行改變的時候其實都等同於生成了一個新的 String 對象,然後將指針指向新的 String 對象,所以經常改變內容的字符串最好不要用 String ,因爲每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了以後, JVM 的 GC 就會開始工作,速度是一定會相當慢的。

而如果是使用 StringBuffer 類則結果就不一樣了,每次結果都會對 StringBuffer 對象本身進行操作,而不是生成新的對象,再改變對象引用。所以在一般情況下我們推薦使用 StringBuffer ,特別是字符串對象經常改變的情況下。而在某些特別情況下,String 對象的字符串拼接其實是被 JVM 解釋成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度並不會比 StringBuffer 對象慢,而特別是以下的字符串對象生成中, String 效率是遠要比 StringBuffer 快的:

在這裏插入圖片描述在這裏插入圖片描述
你會很驚訝的發現,生成 String S1 對象的速度簡直太快了,而這個時候 StringBuffer 居然速度上根本一點都不佔優勢。

其實這是 JVM 的一個把戲,在 JVM 眼裏,這個
在這裏插入圖片描述
其實就是: String S1 = “This is only a simple test”;所以當然不需要太多的時間了

但這裏要注意的是,如果你的字符串是來自另外的 String 對象的話,速度就沒那麼快了,譬如:

String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 + S3 + S4;

這時候 JVM 會規規矩矩的按照原來的方式去做

在大部分情況下 StringBuffer > String

1.2 StringBuffer

Java.lang.StringBuffer

線程安全的可變字符序列。一個類似於 String 的字符串緩衝區,但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但通過某些方法調用可以改變該序列的長度和內容。

可將字符串緩衝區安全地用於多個線程。可以在必要時對這些方法進行同步,因此任意特定實例上的所有操作就好像是以串行順序發生的,該順序與所涉及的每個線程進行的方法調用順序一致。

StringBuffer 上的主要操作是 appendinsert 方法,可重載這些方法,以接受任意類型的數據。每個方法都能有效地將給定的數據轉換成字符串,然後將該字符串的字符追加或插入到字符串緩衝區中。

在這裏插入圖片描述


例如:

如果 str 引用一個當前內容是“start”的字符串緩衝區對象,則此方法調用 str.append("LE") 會使字符串緩衝區含“startLE”

而 str.insert(4, “LE”) 將更改字符串緩衝區,使之包含“starLEt”


在大部分情況下 StringBuilder > StringBuffer

1.3 StringBuilder

java.lang.StringBuilder

java.lang.StringBuilder一個可變的字符序列是JDK1.5新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種情況很普遍)。如果可能,建議優先採用該類,因爲在大多數實現中,它比StringBuffer 要快。兩者的方法基本相同。

從線程安全的角度去看

StringBuffer是線程安全的,而StringBuilder是線程不安全的

【StringBuffer線程安全,StringBuilder線程不安全】

2. 性能測試

這三個類型到底有什麼區別呢?怎麼選擇它們的應用場景呢?

首先,從性能、速度方面來說:

StringBuilder > StringBuffer > String

我們來做一個測試,我們分別使用String和StringBuilder創建變量,然後分別對它們進行加字符串操作,由於時間太短,我們把這個過程使用for循環重複10W遍以放大差距:

public class TestBuffer {
    public static void main(String[] args) {
        //獲取開始時間
        Long start1 = System.currentTimeMillis();
        //String Test
        for (int i = 0;i < 100000;i++) {
            String str = "a";
            str += "b";
        }
        //獲取結束時間
        Long end1 = System.currentTimeMillis();
        //打印出花費的時間
        System.out.println("String花費時間:"+ (end1-start1));

        //StringBuilder Test
        Long start2 = System.currentTimeMillis();
        for (int i = 0; i < 100000;i++) {
            StringBuilder str2 = new StringBuilder("a");
            str2.append("b");
        }
        Long end2 = System.currentTimeMillis();
        System.out.println("StringBuilder花費時間:"+(end2-start2));

        //重複10萬次進行StringBuffer變量加操作
        Long start3 = System.currentTimeMillis();
        for (int i=0;i < 100000;i++)
        {
            StringBuffer str2 = new StringBuffer("a");
            str2.append("b");
        }
        Long end3 = System.currentTimeMillis();
        System.out.println("StringBuffer花費時間:"+(end3-start3));
    }
}

在這裏插入圖片描述
是什麼造成了這種差距呢?

在上面的程序中:
在這裏插入圖片描述

這兩句話看似是對同一個String類型的str對象進行了加操作,但是實際上可不是同一個對象。

事實上,我們先聲明瞭一個String類型的對象,值是"a",把str這個引用指向了這個對象。然後,當我們把這個對象進行**+=**操作的時候,實際上是又創建了一個新的String對象,這個對象的值是"a"+“b"也就是"ab”,然後改變str的引用讓它指向了這個新的對象,原來的對象失去了引用,就被jvm垃圾回收了。

【傳送門----String類】

如果將這兩句代碼
在這裏插入圖片描述
改爲
在這裏插入圖片描述
讓我們看一下執行效果:

在這裏插入圖片描述
哪怕是進行10萬次操作,String所花費的時間也是極少的,這是爲什麼呢?

當我們執行:String str = “a”+“b”;這句話的時候,String會自動把這個對象的值看成"ab",然後在方法區中如果找到了值同樣爲"ab"的,就會直接讓str引用指向它

而 StringBuffer 和 StringBuilder 可不是這樣,這兩兄弟是直接改變自己本身對象的值。

那麼,當我們進行了10萬次操作的時候,快慢差距自然就體現出來了。

3. StringBuffer,StringBuilder的用法

toString()

將StringBuffer,StringBuilder對象轉換爲String字符串,常用在需要輸出的時候,因爲StringBuffer和StringBuilder的對象不能直接輸出,需要調用toString()
在這裏插入圖片描述
append()

用於在字符串的後面追加字符串. 當StringBuffer,StringBuilder中沒有字符串的時候也可以append(),可以用來初始化
在這裏插入圖片描述
insert()

在指定索引位置之前插入字符串
在這裏插入圖片描述

其他方法類比String類中常用的方法

charaAt()

返回指定索引位置的字符,索引從0開始
在這裏插入圖片描述
deleteCharAt()

刪除指定索引位置的字符
在這裏插入圖片描述
delete()

刪除從開始索引到結束索引的字符串
在這裏插入圖片描述
reverse()

反轉字符串
在這裏插入圖片描述


總結

  1. String 適用於少量的字符串操作的情況
  2. StringBuilder 適用於單線程下在字符緩衝區進行大量操作的情況
  3. StringBuffer 適用多線程下在字符緩衝區進行大量操作的情況

文章轉載彙總,原文鏈接

String,StringBuffer與StringBuilder的區別??

String,StringBuffer,StringBuilder三者的使用方法和區別

證明StringBuffer線程安全,StringBuilder線程不安全

發佈了89 篇原創文章 · 獲贊 124 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章