JDK源码解析

1.构造

AbstractStringBuilder(int capacity) {
    if (COMPACT_STRINGS) {
        value = new byte[capacity];
        coder = LATIN1;
    } else {
        value = StringUTF16.newBytesFor(capacity);
        coder = UTF16;
    }
}

创建指定容量的AbstractStringBuilder。

2.比较

int compareTo(AbstractStringBuilder another) {
    if (this == another) {
        return 0;
    }
​
    byte val1[] = value;
    byte val2[] = another.value;
    int count1 = this.count;
    int count2 = another.count;
​
    if (coder == another.coder) {
        return isLatin1() ? StringLatin1.compareTo(val1, val2, count1, count2)
                          : StringUTF16.compareTo(val1, val2, count1, count2);
    }
    return isLatin1() ? StringLatin1.compareToUTF16(val1, val2, count1, count2)
                      : StringUTF16.compareToLatin1(val1, val2, count1, count2);
}

按字典序比较两个AbstractStringBuilder实现的对象。

3.返回

public int capacity() {
    return value.length >> coder;
}

返回当前容量。容量是新插入字符的可用存储容量,超过此容量将进行分配。

4.扩容

public void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > 0) {
        ensureCapacityInternal(minimumCapacity);
    }
}

minimumCapacity 最小期望容量。

确保容量至少等于指定的最小值。如果当前容量小于参数,则将分配一个新的内部数组,并分配更大的容量。

如果 {@code 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);
    }
}

对于 {@code minimumCapacity} 的正值,此方法的行为类似于 {@code ensureCapacity} ,但是它从不同步。

如果 {@code minimumCapacity} 由于数字溢出而是非正数,此方法将抛出 {@code OutOfMemoryError}。

public void setLength(int newLength) {
    if (newLength < 0) {
        throw new StringIndexOutOfBoundsException(newLength);
    }
    ensureCapacityInternal(newLength);
    if (count < newLength) {
        if (isLatin1()) {
            StringLatin1.fillNull(value, count, newLength);
        } else {
            StringUTF16.fillNull(value, count, newLength);
        }
    }
    count = newLength;
}

设置字符序列的长度。

序列被更改为一个新的字符序列,其长度由参数指定。对于每个非负下标kless小于newLength的字符,如果新字符序列下标k处的字符小于旧字符序列的长度,则新字符序列下标k处的字符与旧字符序列下标k处的字符相同;否则,它是空字符 ’ (u0000 ‘ 。换句话说,如果newLength参数小于当前长度,则长度将更改为指定的长度。如果newLength参数大于或等于当前的长度,则会添加足够的空字符('\u0000'),以便长度成为newLength参数。newLength参数必须大于或等于0。

private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = value.length >> coder;
    int newCapacity = (oldCapacity << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    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;
    int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
    if (UNSAFE_BOUND - minCapacity < 0) { // overflow
        throw new OutOfMemoryError();
    }
    return (minCapacity > SAFE_BOUND)
        ? minCapacity : SAFE_BOUND;
}

minCapacity 要求的最小容量

OutOfMemoryError 如果minCapacity小于0或者大于 ( Integer.MAX_VALUE >> coder )

返回至少与给定的最小容量相同的容量。如果满足,返回增加了相同数量+2的当前容量。返回的容量不会大于 {@code (MAX_ARRAY_SIZE >> coder)} 除非给定最小容量大于该值。

5.缩容

public void trimToSize() {
    int length = count << coder;
    if (length < value.length) {
        value = Arrays.copyOf(value, length);
    }
}

尝试减少用于字符序列的存储空间。如果缓冲区大于容纳当前字符序列所需要的大小,那么它将可以调整大小以使空间更有效。调用这个方法可能会影响后续调用capacity()方法返回的值,但不是必需的。

6.修改字符

public void setCharAt(int index, char ch) {
    checkIndex(index, count);
    if (isLatin1() && StringLatin1.canEncode(ch)) {
        value[index] = (byte)ch;
    } else {
        if (isLatin1()) {
            inflate();
        }
        StringUTF16.putCharSB(value, index, ch);
    }
}

位于指定索引位置的字符被设置为ch。这个序列被更改为表示一个与旧字符序列相同的新字符序列,除了它在索引位置包含字符ch之外。index参数必须大于或等于0,并且小于这个序列的长度。

public AbstractStringBuilder replace(int start, int end, String str) {
    int count = this.count;
    if (end > count) {
        end = count;
    }
    checkRangeSIOOBE(start, end, count);
    int len = str.length();
    int newCount = count + len - (end - start);
    ensureCapacityInternal(newCount);
    shift(end, newCount - count);
    this.count = newCount;
    putStringAt(start, str);
    return this;
}

将此序列的子字符串中的字符替换为指定字符串中的字符。子字符串从指定的起始位置开始,并扩展到索引end - 1处的字符,或者如果不存在这样的字符,则扩展到序列的末尾。首先删除子字符串中的字符,然后在开始时插入指定的String(如果需要,这个序列将被加长以适应指定的String)。

7.删除

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;
​​​​​​​}

删除此序列的子字符串中的字符。子字符串从指定的起始位置开始,并扩展到索引end - 1处的字符,或者如果不存在这样的字符,则扩展到序列的末尾。如果start等于end,则不进行任何更改。

public AbstractStringBuilder deleteCharAt(int index) {
    checkIndex(index, count);
    shift(index + 1, -1);
    count--;
    return this;
}

移除此序列中指定位置的字符。这个序列缩短了一个字符。注意:如果给定索引处的字符是一个补充字符,此方法不会删除整个字符。如果需要正确处理补充字符,则通过调用Character确定要删除的字符数。charCount ( thisSequence.codePointAt ( index ) ),其中thisSequence就是这个序列。

8.插入字符串

public AbstractStringBuilder insert(int index, char[] str, int offset, int len)
{
    checkOffset(index, count);
    checkRangeSIOOBE(offset, offset + len, str.length);
    ensureCapacityInternal(count + len);
    shift(index, len);
    count += len;
    putCharsAt(index, str, offset, offset + len);
    return this;
}

将str数组参数的子数组的字符串表示形式插入到该序列中。子数组从指定的偏移量开始,并扩展len字符。子数组的字符被插入到这个序列中由index指定的位置。这个序列的长度增加了len字符。

9.得到子字符串/子序列

public String substring(int start) {
    return substring(start, count);
}

返回一个新String,其中包含当前包含在此字符序列中的字符序列。子字符串从指定的索引开始,并扩展到该序列的末尾。

public CharSequence subSequence(int start, int end) {
    return substring(start, end);
}

返回一个新字符序列,该字符序列是该序列的子序列。表单的此方法的调用 sb.subSequence(begin, end) ,行为与调用 sb.substring(begin, end)。提供这个方法是为了让这个类能够实现CharSequence接口。

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);
}

返回一个新的String,其中包含当前包含在该序列中的字符序列。子字符串从指定的起始位置开始,并扩展到索引end - 1处的字符。

10.查找

public int indexOf(String str) {
    return indexOf(str, 0);
}

返回指定子字符串在此字符串中第一个匹配项的索引。返回的索引是最小值k,其中:this.toString().startsWith(str, k)。如果k不存在这样的值,则返回-1。

public int lastIndexOf(String str) {
    return lastIndexOf(str, count);
}

返回指定子字符串最后一次出现的字符串中的索引。空字符串" "的最后一次出现被认为出现在索引值处this.length()。返回的索引是其中最大的k值: this . toString ( ) . startsWith ( str, k ) 。如果k不存在这样的值,则返回-1。

11.翻转字符串

public AbstractStringBuilder reverse() {
    byte[] val = this.value;
    int count = this.count;
    int coder = this.coder;
    int n = count - 1;
    if (COMPACT_STRINGS && coder == LATIN1) {
        for (int j = (n-1) >> 1; j >= 0; j--) {
            int k = n - j;
            byte cj = val[j];
            val[j] = val[k];
            val[k] = cj;
        }
    } else {
        StringUTF16.reverse(val, count);
    }
    return this;
}

使该字符序列被与其相反的字符序列替换。如果序列中包含任何代理项对,则将其作为单个字符进行反向操作。因此,高-低代理的顺序永远不会颠倒。设n为这个字符序列的字符长度(不是char值中的长度),刚好在执行相反的方法之前。那么新字符序列中索引kin处的字符等于旧字符序列中索引n-k-1处的字符。注意,反向操作可能导致在操作前生成未配对的低代理和高代理的代理对。例如,反转"\uDC00\uD800" 将生成"\uD800\uDC00",这是一个有效的代理对。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值