【JDK源码】StringBuilder类源码分析

StringBuilder类的源码和StringBuffer类除了线程是否同步外,其他并无差别,而他们都有一个共同的父类AbstractStringBuilder ,真正实现核心逻辑的是AbstractStringBuilder 。

源码分析

1、StringBuilder类

/**
 *  StringBuilder继承了AbstractStringBuilder 
 *    实现了Serializable序列化接口,表示对象可序列化,实现了CharSequence字符序列接口,表示可进行字符的相关操作
 **/
public final class StringBuilder extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{
    
    // 与StringBuffer类的构造器一样,通过super()调用父类构造器,append()调用的也是父类ASB的构造器
    public StringBuilder() { super(16);}
    public StringBuilder(String str) { super(str.length() + 16); append(str);}
    public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq);}
    public StringBuilder(int capacity) { super(capacity);}

    // append()/insert()/deleteCharAt()/delete()/indexOf()/lastIndexOf()/replace()/subString()/reverse()等除了不是同步synchronized的,其他与StringBuffer类一样
    ......;
}

小结一下:

  • StringBuilder类的源码可以看出:除了操作字符串线程不安全,其他的特点与StringBuffer类一模一样。

2、AbstractStringBuilder类 

AbstractStringBuilder类是操作可变字符串类(如StringBuffer、StringBuilder)的父类,而子类中的append()/insert()/deleteCharAt()/delete()/reverse()等核心方法的逻辑基本是在父类中实现的。

构造方法

构造器很简单,维护的是一个字符数组来存储字符串。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
    char[] value; //存储字符串的字符数组
    int count; //字符数组中元素的格式
   
    // 将字符串存储在字符数组中
    AbstractStringBuilder() {}
    AbstractStringBuilder(int capacity) {value = new char[capacity];}
}

append()方法

以引用对象类型(如Object、CharSequence、String、StringBuffer、AbstractStringBuilder)作为追加的内容为例,基本步骤如下:

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull(); //1.对象判空检查
 
    int len = str.length();
    ensureCapacityInternal(count + len); //2.确保初始化容量大小
 
    //3.本质是System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    str.getChars(0, len, value, count); 
   
    count += len;
    return this; //4.返回当前对象
}

在StringBuilder对象创建后去追加内容,为什么要确保初始化容量大小?通过构造器创建的StringBuilder对象默认容量大小为16,或者去指定容量大小,而继续追加内容时需要保证追加的内容不会超过容量大小,如果超过了则需要进行扩容处理。

扩容涉及到的方法有下面三个,基本逻辑就是:

  • 追加的字符串长度 + 原有的字符串长度 如果超过字符数组的指定容量大小,会通过newCapacity()增加容量大小;
  • 每次扩容大小为:原字符数组大小*2 + 2 ,如果扩容后容量仍小于追加的字符串长度 + 原有的字符串长度,将扩容后容量默认为字符串长度 + 原有的字符串长度;
  • 字符串并不是无上限追加的,最大为Integer类型大小,极限的取值区间为:[Integer.MAX_VALUE - 8,  Integer.MAX_VALUE) 。
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}
 
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}
 
private int hugeCapacity(int minCapacity) {
    if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
        throw new OutOfMemoryError();
    }
    return (minCapacity > MAX_ARRAY_SIZE)
        ? minCapacity : MAX_ARRAY_SIZE;
}

追加的内容为基本类型也是需要进行是否扩容处理,insert()方法实现的字符串追加,replace()方法实现的字符串替换,也是上面这些步骤。

delete()方法

删除的核心:就是将修剪后的数组copy到目标数组,更新字符数组元素的个数

public AbstractStringBuilder delete(int start, int end) {
    // 参数判断
    if (start < 0)
        throw new StringIndexOutOfBoundsException(start);
    if (end > count)
        end = count;
    if (start > end)
        throw new StringIndexOutOfBoundsException();

    // 修剪后的数组copy到目标数组
    int len = end - start;
    if (len > 0) {
        System.arraycopy(value, start+len, value, start, count-end);
        count -= len; // 删除字符的个数
    }
    return this;
}

public AbstractStringBuilder deleteCharAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    
    System.arraycopy(value, index+1, value, index, count-index-1);
    count--;
    
    return this;
}

看到这儿,应该会发现一个有趣的现象,操作字符串底层是通过操作字符数组来实现的,很多处用到了System.arraycopy()方法,它作用是将原数组拷贝到目标数组,从而实现数组的替换。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值