Java入門系列之StringBuilder、StringBuffer(三)

前言

上一節咱們講解了字符串的特性,除了字符串類外,還有兩個咱們也會常常用到的類,那就是StringBuffer和StringBuilder。由於字符串不可變,因此咱們每次對字符串的修改好比經過鏈接concat、trim等都會建立一個新的字符串對象,那麼咱們如何在不建立字符串垃圾(大量臨時的字符串)的 狀況下操做字符串呢?答案則是使用StringBuffer和StringBuilder,StringBuffer是舊類,可是在Java 5中新增了StringBuilder,而且在Enum,Generics等和Java中的Autoboxing方面進行了重大改進。安全

 

StringBuffer VS StringBuilder

String和StringBuffer之間的主要區別是String是不可變的,而StringBuffer、StringBuilder可變,這也就意味着咱們能夠在建立StringBuffer對象時修改它而不建立任何新對象,這個可變屬性使StringBuffer成爲處理Java中的字符串的理想選擇,同時,這種可變性更加節省時間而且資源消耗更少。固然咱們能夠經過toString將StringBuffer轉換爲String。這兩個類幾乎相同,它們使用具備相同名稱的方法返回相同的結果,咱們看看StringBuffer和StringBuilder源碼中的Append方法便可知其區別:多線程

   @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

 

線程安全:StringBuffer方法是同步的,這意味着一次只能有一個線程調用StringBuffer實例的方法。 另外一方面,StringBuilder方法不一樣步,所以多個線程能夠調用StringBuilder類中的方法而不會被阻塞。因此咱們得出結論,StringBuffer是一個線程安全的類,而StringBuilder則不是。若是咱們正在處理使用多線程的應用程序,那麼使用StringBuilder可能會有線程不安全風險。app

速度:StringBuffer實際上比StringBuilder慢兩到三倍。 這背後的緣由是StringBuffer同步,一次只容許一個對象在一個對象上執行,致使代碼執行速度慢得多。ide

StringBuffer和StringBuilder都有相同的方法(除了StringBuffer類中的synchronized方法聲明外),如下爲常見方法:性能

  • append()
  • insert()
  • replace()
  • delete()
  • reverse()

咱們經過以下示例來使用上述幾個經常使用方法:測試

public class Main {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Buffer no 1");
        System.out.println(sb);

        sb.append(" - and this is appended!");
        System.out.println(sb);
        sb.insert(11, ", this is inserted");
        System.out.println(sb);
        sb.replace(7, 9, "Number");
        System.out.println(sb);
        sb.delete(7, 14);
        System.out.println(sb);
        sb.reverse();
        System.out.println(sb);
    }
}

接下來咱們來對String、StringBuffer、StringBuilder進行性能測試。 ui

  String concatString = "concatString";
        StringBuffer appendBuffer = new StringBuffer("appendBuffer");
        StringBuilder appendBuilder = new StringBuilder("appendBuilder");
        long timerStarted;

        timerStarted = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
            concatString += " another string";
        }
        System.out.println("Time needed for 50000 String concatenations: " + (System.currentTimeMillis() - timerStarted) + "ms");

        timerStarted = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
            appendBuffer.append(" another string");
        }
        System.out.println("Time needed for 50000 StringBuffer appends: " + (System.currentTimeMillis() - timerStarted) + "ms");

        timerStarted = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
            appendBuilder.append(" another string");
        }
        System.out.println("Time needed for 50000 StringBuilder appends: " + (System.currentTimeMillis() - timerStarted) + "ms");

如上打印輸出因Java虛擬機而異,從如上基準測試中咱們仍是能夠看出StringBuilder是字符串操做中最快的,次之StringBuffer,它比StringBuilder慢1倍多,最後是String這是字符串操做中最慢的。使用StringBuilder的時間比普通的String快一系列。那麼是否是說明咱們對字符串操做時,徹底摒棄使用字符串呢?固然不是,凡是沒絕對,好比對字符串只是簡單操做,直接使用字符串也沒有多大性能損耗。this

String:不可變(這意味着更多的內存消耗)而且在進行字符串操做時很是慢,可是線程安全。spa

StringBuffer:可變且內存有效,而且是線程安全的。 與更快的StringBuilders相比,它們的降低速度是速度。線程

StringBuilder:可變的且內存有效,它們是字符串操做中最快的,但不幸的是它不是線程安全的。

總結

本節咱們比較了StringBuffer和StringBuilder的區別,算是作一個筆記,沒有什麼理解難點,若是咱們基於以上事實結論考慮,咱們始終會作出正確的選擇!

相關文章
相關標籤/搜索