java StringBuilder源码阅读

本文主要对StringBuilder源代码中的重点难点方法进行解析。

StringBuilder(String str) 创建一个新的StringBuilder,其初始内容为传入的字符串str
@HotSpotIntrinsicCandidate
public StringBuilder(String str) {
    super(str);
}

AbstractStringBuilder(String str) {
    int length = str.length();
    // 新创建的StringBuilder的长度为传入的字符串的长度+16
    int capacity = (length < Integer.MAX_VALUE - 16)
            ? length + 16 : Integer.MAX_VALUE;
    final byte initCoder = str.coder();
    coder = initCoder;
    value = (initCoder == LATIN1)
            ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
    // 将str的内容append到StringBuilder后面
    append(str);
}

 

ensureCapacityInternal(int minimumCapacity) 确保StringBuilder内部的数组长度能够容纳至少minimumCapacity个字符
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    int oldCapacity = value.length >> coder;
    if (minimumCapacity - oldCapacity > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity) << coder);
    }
}

// 生成新的数组长度(以字符为单位,如果一个字符对应多个bit则调用者自行左移)
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = value.length >> coder;
    // 默认新长度=旧长度*2+2
    int newCapacity = (oldCapacity << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    // MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
    // 由于MAX_ARRAY_SIZE代表的是字节长度,所以需要右移换算成字符长度
    int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
    return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}

private int hugeCapacity(int minCapacity) {
    int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
    // SAFE_BOUND是安全界限,UNSAFE_BOUND是不安全界限
    // 当minCapacity大于安全界限,小于等于不安全界限时返回minCapacity,勉强可用
    // 但是如果minCapacity大于不安全,则目前虚拟机无法承载这么大的数组,报错
    int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
    if (UNSAFE_BOUND - minCapacity < 0) { // overflow
        throw new OutOfMemoryError();
    }
    return (minCapacity > SAFE_BOUND)
        ? minCapacity : SAFE_BOUND;
}

 

AbstractStringBuilder::appendNull() 在StringBuilder后方加入'null'四个字符
private AbstractStringBuilder appendNull() {
    ensureCapacityInternal(count + 4);
    int count = this.count;
    byte[] val = this.value;
    if (isLatin1()) {
        val[count++] = 'n';
        val[count++] = 'u';
        val[count++] = 'l';
        val[count++] = 'l';
    } else {
        count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
    }
    this.count = count;
    return this;
}

 

StringBuilder::append(String str) 将str的内容接到StringBuilder后方
@Override
@HotSpotIntrinsicCandidate
public StringBuilder append(String str) {
    super.append(str); // 调用AbstractStringBuilder::append(String str)
    return this;
}

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

private final void putStringAt(int index, String str) {
    if (getCoder() != str.coder()) {
        inflate();
    }
    str.getBytes(value, index, coder);
}

// 如果当前StringBuilder的编码为Latin1编码,则把它转换成UTF16编码
// UTF16编码由于兼容Latin1编码所以没必要转换
// 例如,Latin1码元为0x1f ,转换成UTF16后码元为0x001f
private void inflate() {
    if (!isLatin1()) {
        return;
    }
    byte[] buf = StringUTF16.newBytesFor(value.length);
    StringLatin1.inflate(value, 0, buf, 0, count);
    this.value = buf;
    this.coder = UTF16;
}

 

StringBuilder::delete(int start, int end) 删除start和end之间的字符
@Override
public StringBuilder delete(int start, int end) {
    super.delete(start, end);
    return this;
}

public AbstractStringBuilder delete(int start, int end) {
    int count = this.count;
    if (end > count) {
        end = count;
    }
    checkRangeSIOOBE(start, end, count);
    int len = end - start;
    if (len > 0) {
        // 左移
        shift(end, -len);
        this.count = count - len;
    }
    return this;
}

// 检查start和end的合法性
private static void checkRangeSIOOBE(int start, int end, int len) {
    if (start < 0 || start > end || end > len) {
        throw new StringIndexOutOfBoundsException(
            "start " + start + ", end " + end + ", length " + len);
    }
}

private void shift(int offset, int n) {
    // 从offset处开始复制,每个元素向前移动n,共移动count-offset个元素
    System.arraycopy(value, offset << coder,
                        value, (offset + n) << coder, (count - offset) << coder);
}

/**
* @param      src      源数组
* @param      srcPos   源数组复制起始点
* @param      dest     目标数组
* @param      destPos  目标数组复制起始点
* @param      length   要复制的元素个数
*/
public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

 

StringBuilder::replace(int start, int end, String str) 替换操作
@Override
public StringBuilder replace(int start, int end, String str) {
    super.replace(start, end, str);
    return this;
}

public AbstractStringBuilder replace(int start, int end, String str) {
    int count = this.count;
    if (end > count) {
        end = count;
    }
    // 检查start、end的越界情况
    checkRangeSIOOBE(start, end, count);
    int len = str.length();
    // 获取新长度、确保新长度合法
    int newCount = count + len - (end - start);
    ensureCapacityInternal(newCount);
    // 右移
    shift(end, newCount - count);
    this.count = newCount;
    // 从start处将str的内容放入
    putStringAt(start, str);
    return this;
}

 

posted @ 2021-03-29 22:15  榆木脑袋0v0  阅读(163)  评论(0)    收藏  举报