【Java】JDK源码分析——AbstractStringBuilder

指定初始化容量,根据容量对数组进行初始化。

3. length方法


获取字符串长度。

AbstractStringBuilder.java中的相关代码:


    @Override

    public int length() {

        return count;

	}



4. capacity方法


获取容量,即最多可以保存的字符数量。

AbstractStringBuilder.java中的相关代码:


	public int capacity() {

    	// 返回数组长度

        return value.length;

	}



5. ensureCapacity方法


对数组的容量进行检测,并在容量小于要求时进行扩容。

AbstractStringBuilder.java中的相关代码:


	public void ensureCapacity(int minimumCapacity) {

    	// 若要求的容量大于0

        if (minimumCapacity > 0)

            // 则调用ensureCapacityInternal方法

            ensureCapacityInternal(minimumCapacity);

	}



1)ensureCapacityInternal方法

AbstractStringBuilder.java中的相关代码:


    private void ensureCapacityInternal(int minimumCapacity) {

        // 若要求的容量大于当前数组的长度,即需要扩容

        if (minimumCapacity - value.length > 0) {

            // 调用newCapacity方法,获取扩容后的容量

            // 将当前字符数组的内容复制到扩容后的新数组中,并返回新数组

            value = Arrays.copyOf(value,

                    newCapacity(minimumCapacity));

        }

	}



2)newCapacity方法

AbstractStringBuilder.java中的相关代码:


    private int newCapacity(int minCapacity) {

        // 计算新的容量为当前容量乘的2倍再加2

        int newCapacity = (value.length << 1) + 2;

        // 如果新计算的容量还是小于要求的容量

        if (newCapacity - minCapacity < 0) {

            // 设置新容量为要求的容量

            newCapacity = minCapacity;

        }

        // 如果新容量小于等于0或者新容量超过最大容量

        // 则返回调用hugeCapacity方法的结果,该方法用于获得一个相对较大的容量

        // 否则,返回新计算的容量

        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)

            ? hugeCapacity(minCapacity)

            : newCapacity;

	}



3)hugeCapacity方法

AbstractStringBuilder.java中的相关代码:


	private int hugeCapacity(int minCapacity) {

    	// 若要求的容量大于整型数据的最大值,则抛出异常

        if (Integer.MAX_VALUE - minCapacity < 0) { 

            throw new OutOfMemoryError();

        }

        // 若要求的容量大于最大容量,则返回要求的容量,否则返回最大容量

        // 即返回两者中较大的一个

        return (minCapacity > MAX_ARRAY_SIZE)

            ? minCapacity : MAX_ARRAY_SIZE;

	}



6. trimToSize方法


该方法用于释放字符数组中没有用到空间。

AbstractStringBuilder.java中的相关代码:


	public void trimToSize() {

    	// 若已经使用的容量小于总容量

        if (count < value.length) {

            // 根据已经使用的容量,创建新的数组,将原数组的内容复制到新数组中

            // 保存新数组

            value = Arrays.copyOf(value, count);

        }

	}



7. setLength


该方法用于设置字符串的长度。

AbstractStringBuilder.java中的相关代码:


	public void setLength(int newLength) {

    	// 若设置的长度小于0,则抛出异常

        if (newLength < 0)

            throw new StringIndexOutOfBoundsException(newLength);

        // 进行扩容

        ensureCapacityInternal(newLength);



        // 如果已经使用的空间小于总空间

        if (count < newLength) {

            // 用’\0’对没有用到空间进行填充

            Arrays.fill(value, count, newLength, '\0');

        }

        // 设置已经使用使用的空间的数量

        count = newLength;

	}



8.charAt方法


获取字符串中指定位置的字符。

AbstractStringBuilder.java中的相关代码:


    @Override

	public char charAt(int index) {

    	// 若指定的位置小于0,或超过字符串的长度,则抛出异常

        if ((index < 0) || (index >= count))

            throw new StringIndexOutOfBoundsException(index);

        // 返回数组中对应位置的字符

        return value[index];

	}



9. getChars方法


将字符串中从srcBegin开始到srcEnd结束的字符填充到dst数组从dstBegin开始的位置。

AbstractStringBuilder.java中的相关代码:


    public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin){

    	// 若字符串起始位置小于0

        if (srcBegin < 0)

            throw new StringIndexOutOfBoundsException(srcBegin);

        // 若字符串终止位置小于0,或字符串终止位置超出了字符串的长度

        if ((srcEnd < 0) || (srcEnd > count))

            throw new StringIndexOutOfBoundsException(srcEnd);

        // 若字符串的起始位置超过了字符串的终止位置

        if (srcBegin > srcEnd)

            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");

        // 复制字符串的内容到数组中。

        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);

	}



10. setCharAt方法


将字符串中指定位置index处的字符设置为指定字符ch。

AbstractStringBuilder.java中的相关代码:


	public void setCharAt(int index, char ch) {

    	// 若起始位置小于0,或超过字符串最大长度

        if ((index < 0) || (index >= count))

            throw new StringIndexOutOfBoundsException(index);

        // 设置字符数组index处字符为ch

        value[index] = ch;

	}



11. append方法


向字符串末尾附加一个字符串形式的对象。

1)参数为String

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder append(String str) {

    	// 若附加的字符串为空

        if (str == null)

            // 则调用appendNull方法,附加”null”,并返回

            return appendNull();

        // 若附加的字符串不为空

        // 获取附加的字符串的长度

        int len = str.length();

        // 进行扩容,新字符串长度为原长度count+附加长度len

        ensureCapacityInternal(count + len);

        // 调用附加字符串的getChars方法,从源字符串末尾count位置开始添加

        str.getChars(0, len, value, count);

        // 设置新字符串的长度

        count += len;

        // 返回

        return this;

	}



参数为StringBuffer和AbstractStringBuilder时的处理过程也是如此。

a)appendNull方法

AbstractStringBuilder.java中的相关代码:


	private AbstractStringBuilder appendNull() {

    	int c = count;

    	// 扩容

    	ensureCapacityInternal(c + 4);

    	// 拼接”null”

    	final char[] value = this.value;

    	value[c++] = 'n';

    	value[c++] = 'u';

    	value[c++] = 'l';

    	value[c++] = 'l';

    	// 设置新字符串的长度

    	count = c;

    	// 返回

    	return this;

	}



2)参数为Object

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder append(Object obj) {

    	// 调用Object对象的toString方法,拼接

        return append(String.valueOf(obj));

	}



3)参数为char[]

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder append(char[] str) {

    	// 获取附加的字符串的长度

        int len = str.length;

        // 扩容

        ensureCapacityInternal(count + len);

        // 将str中长度为len的内容从起始位置0复制到value数组count后

        System.arraycopy(str, 0, value, count, len);

        // 设置新字符串的长度

        count += len;

        // 返回

        return this;

	}



4)参数为boolean

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder append(boolean b) {

    	// 为true

        if (b) {

            // 容量加4

            ensureCapacityInternal(count + 4);

            // 拼接”true”

            value[count++] = 't';

            value[count++] = 'r';

            value[count++] = 'u';

            value[count++] = 'e';

        } else {// 为false

            // 容量加5

            ensureCapacityInternal(count + 5);

            // 拼接”fasle”

            value[count++] = 'f';

            value[count++] = 'a';

            value[count++] = 'l';

            value[count++] = 's';

            value[count++] = 'e';

        }

        // 返回

        return this;

	}



5)参数为char

AbstractStringBuilder.java中的相关代码:


    @Override

	public AbstractStringBuilder append(char c) {

    	// 容量加1

        ensureCapacityInternal(count + 1);

        // 拼接字符

        value[count++] = c;

        // 返回

        return this;

	}



6)参数为int

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder append(int i) {

    	// 若为整型的最小值,即-2147483648

        if (i == Integer.MIN_VALUE) {

            // 直接拼接

            append("-2147483648");

            // 返回

            return this;

        }

        // 通过调用Integer的静态方法stringSize,获取i的长度

        int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1

                                     : Integer.stringSize(i);

        // 计算拼接后的长度

        int spaceNeeded = count + appendedLength;

        // 扩容

        ensureCapacityInternal(spaceNeeded);

        // 调用Integer的getChars方法进行拼接

        Integer.getChars(i, spaceNeeded, value);

        // 设置新字符串长度

        count = spaceNeeded;

        返回

        return this;

	}



参数为long时,处理过程和int相似,只不过在拼接字符串时调用的是Long的静态方法getChars。

7)参数为float

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder append(float f) {

    	// 调用FloatingDecimal的静态方法appendTo方法进行拼接

        FloatingDecimal.appendTo(f,this);

        // 返回

        return this;

	}



参数double与float处理过程完全相同。

12. delete方法


删除字符串中指定开始位置和终止位置之间的字符。

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder delete(int start, int end) {

    	// 若起始位置小于0

        if (start < 0)

            throw new StringIndexOutOfBoundsException(start);

        // 若终止位置超过字符串长度

        if (end > count)

            // 设置终止位置为字符串末尾

            end = count;

        // 若起始位置大于终止位置

        if (start > end)

            throw new StringIndexOutOfBoundsException();

        // 计算需要删除字符串的长度

        int len = end - start;

        // 若需要删除字符串的长度大于0

        if (len > 0) {

            // 将终止位置后面的字符串复制到起始位置后面

            System.arraycopy(value, start+len, value, start, count-end);

            // 设置删除后的字符串的长度

            count -= len;

        }

        // 返回

        return this;

	}



13. deleteCharAt方法


删除字符串中指定位置的字符。

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder deleteCharAt(int index) {

    	// 若指定位置小于0,或超过字符串长度

        if ((index < 0) || (index >= count))

            throw new StringIndexOutOfBoundsException(index);

        // 将index后面的字符串复制到index处

        System.arraycopy(value, index+1, value, index, count-index-1);

        // 新字符串长度为源字符串长度减1

        count--;

        // 返回

        return this;

	}



14.replace方法


将起始位置start和终止位置end之间的字符串替换为字符串str。

AbstractStringBuilder.java中的相关代码:


	public AbstractStringBuilder replace(int start, int end, String str) {

    	// 若起始位置小于0

        if (start < 0)

            throw new StringIndexOutOfBoundsException(start);

        // 若起始位置超出了字符串的长度

        if (start > count)

            throw new StringIndexOutOfBoundsException("start > length()");

        // 若起始位置大于终止位置

        if (start > end)

            throw new StringIndexOutOfBoundsException("start > end");

        // 若终止位置超出字符串长度

        if (end > count)

            // 设置终止位置为字符串的末尾

            end = count;

        // 获取需要替换进来的字符串的长度

        int len = str.length();

        // 计算替换后的长度:原来的长度+替换进来的长度-替换后被覆盖的长度

        int newCount = count + len - (end - start);

        // 扩容

        ensureCapacityInternal(newCount);

        

        // 从替换后被覆盖的位置开始将后面的字符复制到

        // 加入替换进来的字符串后的末尾



### 最后

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节

### 美团面试经验
![美团面试](https://img-blog.csdnimg.cn/img_convert/df1e667721f4d713e3f01b18a70758f2.webp?x-oss-process=image/format,png)
字节面试经验
![字节面试](https://img-blog.csdnimg.cn/img_convert/2bd7b07220faf4d7727cbab36fe3ab6b.webp?x-oss-process=image/format,png)
菜鸟面试经验
![菜鸟面试](https://img-blog.csdnimg.cn/img_convert/2eca1071424bf878a2f7d043f88241de.webp?x-oss-process=image/format,png)
蚂蚁金服面试经验
![蚂蚁金服](https://img-blog.csdnimg.cn/img_convert/18355751801d58eaf2e54f56ca62b4f0.webp?x-oss-process=image/format,png)
唯品会面试经验
![唯品会](https://img-blog.csdnimg.cn/img_convert/6f15b98b280b9c90b3788906bccf1374.webp?x-oss-process=image/format,png)

>因篇幅有限,图文无法详细发出


xception("start > length()");

        // 若起始位置大于终止位置

        if (start > end)

            throw new StringIndexOutOfBoundsException("start > end");

        // 若终止位置超出字符串长度

        if (end > count)

            // 设置终止位置为字符串的末尾

            end = count;

        // 获取需要替换进来的字符串的长度

        int len = str.length();

        // 计算替换后的长度:原来的长度+替换进来的长度-替换后被覆盖的长度

        int newCount = count + len - (end - start);

        // 扩容

        ensureCapacityInternal(newCount);

        

        // 从替换后被覆盖的位置开始将后面的字符复制到

        // 加入替换进来的字符串后的末尾



### 最后

毕竟工作也这么久了 ,除了途虎一轮,也七七八八面试了不少大厂,像阿里、饿了么、美团、滴滴这些面试过程就不一一写在这篇文章上了。我会整理一份详细的面试过程及大家想知道的一些问题细节

### 美团面试经验
[外链图片转存中...(img-UXshgLGd-1714497724852)]
字节面试经验
[外链图片转存中...(img-FpMdKtTR-1714497724853)]
菜鸟面试经验
[外链图片转存中...(img-1DLZCorr-1714497724853)]
蚂蚁金服面试经验
[外链图片转存中...(img-fp9mHkUt-1714497724853)]
唯品会面试经验
[外链图片转存中...(img-7swGW2f0-1714497724853)]

>因篇幅有限,图文无法详细发出


> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**
  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值