StringBuilder&StringBuffer 源碼閱讀
阿新 • • 發佈:2019-03-09
簡單 else ews bst @param off star 計算 nco
StringBuilder 和 StringBuffer
StringBuilder 和 StringBuffer 都繼承了 AbstractStringBuilder 類,所有實際的字符操作都在父類實現,
主要的區別是 StringBuilder 只是簡單的調用父類方法,而 StringBuffer 的寫操作都添加了 synchronized 關鍵字。
StringBuffer 是線程安全的,而 StringBuilder 不是線程安全的。
AbstractStringBuilder
- 屬性說明
/** * 可變的字符序列 * * @author Michael McCloskey * @author Martin Buchholz * @author Ulf Zibis * @since 1.5 */ abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * 用於字符存儲的字節數組 */ byte[] value; /** * 編碼器 */ byte coder; /** * 字符總數 */ int count;
- 追加字符
/** * 往可變字符序列中追加 boolean 值 * * @param b 一個 boolean 值 */ public AbstractStringBuilder append(boolean b) { // 嘗試進行擴容 ensureCapacityInternal(count + (b ? 4 : 5)); // 讀取當前字符數到局部變量表 int count = this.count; // 讀取字節數組到局部變量表 final byte[] val = value; // 1)如果是 LATIN1 編碼 if (isLatin1()) { // 追加字符 if (b) { val[count++] = 't'; val[count++] = 'r'; val[count++] = 'u'; val[count++] = 'e'; } else { val[count++] = 'f'; val[count++] = 'a'; val[count++] = 'l'; val[count++] = 's'; val[count++] = 'e'; } // 2)如果是 UTF16 編碼 } else { if (b) { count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e'); } else { count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e'); } } this.count = count; return this; } /** * 往可變字符序列中追加單個字符 * * @param c 單個字符 */ @Override public AbstractStringBuilder append(char c) { ensureCapacityInternal(count + 1); if (isLatin1() && StringLatin1.canEncode(c)) { value[count++] = (byte)c; } else { if (isLatin1()) { inflate(); } StringUTF16.putCharSB(value, count++, c); } return this; } /** * 往可變字符序列中追加 int 值 * * @param i 一個 int 值 */ public AbstractStringBuilder append(int i) { final int count = this.count; final int spaceNeeded = count + Integer.stringSize(i); ensureCapacityInternal(spaceNeeded); if (isLatin1()) { Integer.getChars(i, spaceNeeded, value); } else { StringUTF16.getChars(i, count, spaceNeeded, value); } this.count = spaceNeeded; return this; } /** * 往可變字符序列中追加 long 值 * * @param l 一個 long 值 */ public AbstractStringBuilder append(long l) { final int count = this.count; final int spaceNeeded = count + Long.stringSize(l); ensureCapacityInternal(spaceNeeded); if (isLatin1()) { Long.getChars(l, spaceNeeded, value); } else { StringUTF16.getChars(l, count, spaceNeeded, value); } this.count = spaceNeeded; return this; } /** * 往可變字符序列中追加 float 值 * * @param f 一個浮點值 */ public AbstractStringBuilder append(float f) { FloatingDecimal.appendTo(f,this); return this; } /** * 往可變字符序列中追加 double 值 * * @param d 一個 double 值 */ public AbstractStringBuilder append(double d) { FloatingDecimal.appendTo(d,this); return this; } /** * 往可變字符序列中追加對象 * * @param obj 一個對象 */ public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); } /** * 往可變字符序列中追加字符串 * * @param str 一個字符串 */ public AbstractStringBuilder append(String str) { if (str == null) { return appendNull(); } final int len = str.length(); ensureCapacityInternal(count + len); putStringAt(count, str); count += len; return this; } /** * 往可變字符序列中追加字符數組 * * @param str 字符數組 */ public AbstractStringBuilder append(char[] str) { final int len = str.length; ensureCapacityInternal(count + len); appendChars(str, 0, len); return this; } /** * 往可變字符序列中追加字符序列 * * @param s 目標字符序列 */ @Override public AbstractStringBuilder append(CharSequence s) { if (s == null) { return appendNull(); } if (s instanceof String) { return this.append((String)s); } if (s instanceof AbstractStringBuilder) { return this.append((AbstractStringBuilder)s); } return this.append(s, 0, s.length()); }
- 擴容過程
/** * 嘗試進行擴容 */ private void ensureCapacityInternal(int minimumCapacity) { // 讀取舊容量 overflow-conscious code final int oldCapacity = value.length >> coder; // 所需最小容量 > 舊容量 if (minimumCapacity - oldCapacity > 0) { // 擴容並拷貝源字節數組 value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder); } } /** * 返回大於 minCapacity 的最小容量值 * * @param minCapacity 期望的最小容量 */ private int newCapacity(int minCapacity) { // overflow-conscious code final int oldCapacity = value.length >> coder; // 雙倍擴容 + 2 int newCapacity = (oldCapacity << 1) + 2; // 擴容後新容量還是 < 期望最小容量,則使用期望最小容量 if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } final int SAFE_BOUND = MAX_ARRAY_SIZE >> coder; // 一般不會走 hugeCapacity return newCapacity <= 0 || SAFE_BOUND - newCapacity < 0 ? hugeCapacity(minCapacity) : newCapacity; } private int hugeCapacity(int minCapacity) { final int SAFE_BOUND = MAX_ARRAY_SIZE >> coder; final int UNSAFE_BOUND = Integer.MAX_VALUE >> coder; if (UNSAFE_BOUND - minCapacity < 0) { // overflow throw new OutOfMemoryError(); } return minCapacity > SAFE_BOUND ? minCapacity : SAFE_BOUND; }
- 插入字符
/**
* 在目標索引處插入 boolean 值
*
* @param offset 目標索引
* @param b 一個 boolean 值
*/
public AbstractStringBuilder insert(int offset, boolean b) {
return insert(offset, String.valueOf(b));
}
/**
* 在目標索引 offset 處插入字符串。
*
* @param offset 目標索引
* @param str 字符串
*/
public AbstractStringBuilder insert(int offset, String str) {
// 校驗索引的合法性
checkOffset(offset, count);
// 目標字符為 null,則插入 'null'
if (str == null) {
str = "null";
}
// 計算目標字符長度
final int len = str.length();
// 嘗試擴容
ensureCapacityInternal(count + len);
// 目標索引處及其之後的字符數組集體右移 len 個位置
shift(offset, len);
count += len;
// 插入目標字符串到指定索引 offset 處
putStringAt(offset, str);
return this;
}
/**
* 通過數組拷貝完成子數組遷移
*
* @param offset 目標索引
* @param n
*/
private void shift(int offset, int n) {
System.arraycopy(value, offset << coder,
value, offset + n << coder, count - offset << coder);
}
- 刪除字符
/**
* 刪除目標索引 start 和 end 之間的所有字符,包括起始不包括結束
*
* @param start 起始索引,包含
* @param end 結束索引,不包含
*/
public AbstractStringBuilder delete(int start, int end) {
// 從堆內存加載數據到棧局部變量表
final int count = this.count;
if (end > count) {
end = count;
}
checkRangeSIOOBE(start, end, count);
final int len = end - start;
if (len > 0) {
// 從 start 索引處開始的子字符數組集體左移 len 個位置
shift(end, -len);
this.count = count - len;
}
return this;
}
/**
* 刪除指定索引 index 處的單個字符
*
* @param index 待移除字符的索引
*/
public AbstractStringBuilder deleteCharAt(int index) {
checkIndex(index, count);
shift(index + 1, -1);
count--;
return this;
}
- 截取子字符串
/**
* 截取起始索引 start 到結束索引 end 之間的子字符串
*
* @param start 起始索引,包括
* @param end 結束索引,不包括
*/
@Override
public CharSequence subSequence(int start, int end) {
return substring(start, end);
}
/**
* 截取起始索引 start 到結束索引 end 之間的子字符串
*
* @param start 起始索引,包括
* @param end 結束索引,不包括
*/
public String substring(int start, int end) {
checkRangeSIOOBE(start, end, count);
if (isLatin1()) {
return StringLatin1.newString(value, start, end - start);
}
return StringUTF16.newString(value, start, end - start);
}
/**
* 從起始索引 start 開始,截取剩余的子字符串
*
* @param start 起始索引,包括
*/
public String substring(int start) {
return substring(start, count);
}
StringBuilder&StringBuffer 源碼閱讀