將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中。
更多精彩內容請關注微信公衆號: