JDK源碼(十九):StringBuilder和StringBuffer

將StringBuilder和StringBuffer放在一起是因爲這2個類的代碼差不多,只是StringBuilder是線程不安全的,而StringBuffer是線程安全的。

當對字符串進行修改的時候,需要使用 StringBuffer 和 StringBuilder 類。和 String 類不同的是,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,並且不產生新的未使用對象。StringBuilder 類在 Java 5 中被提出,它和 StringBuffer 之間的最大不同在於 StringBuilder 的方法不是線程安全的(不能同步訪問)。由於 StringBuilder 相較於 StringBuffer 有速度優勢,所以多數情況下建議使用 StringBuilder 類。然而在應用程序要求線程安全的情況下,則必須使用 StringBuffer 類。

線程安全

public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    stringBuilder.append("a");
                }
                System.out.println("builder: " +stringBuilder.length());
            }).start();
        }

        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    stringBuffer.append("a");
                }
                System.out.println("buffer: " +stringBuffer.length());
            }).start();
        }
    }

運行多次結果顯示StringBuilder的長度一般小於100000,而StringBuffer的長度總是等於100000。

append

StringBuffer:

    @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

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

StringBuilder:

    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

從上面可以看出StringBuffer的append方法上有synchronized,並且方法裏還有一個toStringCache的變量。這個變量只在toString方法中有用,當修改StringBuffer時清除。

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

toStringCache是對StringBuffer的優化,但是只有在連續調用toString方法,這個toStringCache纔有用,因爲當對字符串進行操作時,toStringCache會被賦值爲null。


 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

2個類都繼承了AbstractStringBuilder,所以super.append的方法即調用了AbstractStringBuilder類中的append方法

public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

ensureCapacityInternal方法是先判斷char數組的長度夠不夠,如果不夠,則會重新創建一個char數組並賦值給原來的數組。

 private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

然後調用String的getChars方法將內容加到數組value中。

更多精彩內容請關注微信公衆號:

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