JAVA中的String,StringBuffer,StringBuilder筆記

相對於不可變的String來說,StringBuffer類就提供了更靈活更高效的字符串處理方式

          String:值不可變。

                       每次對String的操作都會生成新的String對象,效率低,耗費大量內存空間。

StringBuffer:值可變,默認分配16字節長度的緩衝區,當字符串超過該大小時,會自動增加緩衝區長度,而不是生成新的對象。

                       在進行字符串處理時,不生成新的對象,在內存使用上要優於String。

StringBuffer不支持簡寫方式,只能通過new來創建對象,

//不能像String一樣寫成:
String s1="abc"
//只能通過new來創建對象,如下:
StringBuffer str1 = new StringBuffer();  // 分配16個字節長度的緩衝區
StringBuffer str2 = =new StringBuffer(512);  // 分配512個字節長度的緩衝區
// 在緩衝區中存放了字符串,並在後面預留了16個字節長度的空緩衝區
StringBuffer str3 = new StringBuffer("https://blog.csdn.net/mountain_hua");

StringBuffer類的主要方法

StringBuffer類中的方法主要偏重於對於字符串的操作,例如追加、插入和刪除等,這個也是StringBuffer類和String類的主要區別。實際開發中,如果需要對一個字符串進行頻繁的修改,建議使用 StringBuffer。

1) append() 方法

append() 方法用於向當前字符串的末尾追加內容,類似於字符串的連接。調用該方法以後,StringBuffer對象的內容也發生改變,例如:

StringBuffer str = new StringBuffer(“mountain_hua”);
str.append(true);

則對象str的值將變成”mountain_huatrrue”。注意是str指向的內容變了,不是str的指向變了。

字符串的”+“操作實際上也是先創建一個StringBuffer對象,然後調用append()方法將字符串片段拼接起來,最後調用toString()方法轉換爲字符串。

這樣看來,String的連接操作就比StringBuffer多出了一些附加操作,效率上必然會打折扣。

但是,對於長度較小的字符串,”+“操作更加直觀,更具可讀性,有些時候可以稍微犧牲一下效率。

2)  deleteCharAt()

deleteCharAt() 方法用來刪除指定位置的字符,並將剩餘的字符形成新的字符串。例如:

StringBuffer str = new StringBuffer("abcdef");
str. deleteCharAt(3);

該代碼將會刪除索引值爲3的字符,即”d“字符。

你也可以通過delete()方法一次性刪除多個字符,例如:

StringBuffer str = new StringBuffer("abcdef");
str.delete(1, 4);

該代碼會刪除索引值爲1~4之間的字符,包括索引值1,但不包括4。

3) insert() 方法

insert() 用來在指定位置插入字符串,可以認爲是append()的升級版。例如:

StringBuffer str = new StringBuffer("abcdef");
str.insert(3, "xyz");

最後str所指向的字符串爲 abcdxyzef。

4) setCharAt() 方法

setCharAt() 方法用來修改指定位置的字符。例如:

StringBuffer str = new StringBuffer("abcdef");
str.setCharAt(3, 'z');

該代碼將把索引值爲3的字符修改爲 z,最後str所指向的字符串爲 abczef。

以上僅僅是部分常用方法的簡單說明,更多方法和解釋請查閱API文檔。

String和StringBuffer的效率對比

爲了更加明顯地看出它們的執行效率,下面的代碼,將26個英文字母加了10000次。

public class Demo {
    public static void main(String[] args){
        String fragment = "abcdefghijklmnopqrstuvwxyz";
        int times = 10000;
       
        // 通過String對象
        long timeStart1 = System.currentTimeMillis();
        String str1 = "";
        for (int i=0; i<times; i++) {
            str1 += fragment;
        }
        long timeEnd1 = System.currentTimeMillis();
        System.out.println("String: " + (timeEnd1 - timeStart1) + "ms");
       
        // 通過StringBuffer
        long timeStart2 = System.currentTimeMillis();
        StringBuffer str2 = new StringBuffer();
        for (int i=0; i<times; i++) {
            str2.append(fragment);
        }
        long timeEnd2 = System.currentTimeMillis();
        System.out.println("StringBuffer: " + (timeEnd2 - timeStart2) + "ms");
    }
}

運行結果:
String: 5287ms
StringBuffer: 3ms

結論很明顯,StringBuffer的執行效率比String快上千倍,這個差異隨着疊加次數的增加越來越明顯,當疊加次數達到30000次的時候,運行結果爲:
String: 35923ms
StringBuffer: 8ms

所以,強烈建議在涉及大量字符串操作時使用StringBuffer。

StringBuilder類

StringBuilder類和StringBuffer類功能基本相似,方法也差不多,主要區別在於StringBuffer類的方法是多線程安全的,而StringBuilder不是線程安全的,相比而言,StringBuilder類會略微快一點。

StringBuffer、StringBuilder、String中都實現了CharSequence接口。

CharSequence是一個定義字符串操作的接口,它只包括length()、charAt(int index)、subSequence(int start, int end) 這幾個API。

StringBuffer、StringBuilder、String對CharSequence接口的實現過程不一樣,如下圖所示:


圖1  對CharSequence接口的實現


可見,String直接實現了CharSequence接口;StringBuilder 和 StringBuffer都是可變的字符序列,它們都繼承於AbstractStringBuilder,實現了CharSequence接口。

總結

線程安全:

  • StringBuffer:線程安全
  • StringBuilder:線程不安全


速度:
一般情況下,速度從快到慢爲 StringBuilder > StringBuffer > String,當然這是相對的,不是絕對的。

使用環境:

  • 操作少量的數據使用 String;
  • 單線程操作大量數據使用 StringBuilder;
  • 多線程操作大量數據使用 StringBuffer。

本文寫作參考微學苑,致敬原作者,如有侵權請聯繫刪除

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章