StringBuffer和StringBuilder的append机制

1.StringBuffer和StringBuilder简介

在Java中,我们除了可以通过String类创建和处理字符串之外,还可以使用StringBuffer和StringBuilder类来处理字符串。

其中,String类定义的字符串内容不可变,所以String属于不可变字符串。

而StringBuffer和StringBuilder定义的字符串内容可变,这两者属于可变字符串,并且StringBuffer和StringBuilder,对字符串的处理效率比String类更高。

StringBuffer和StringBuilder其实都是继承自AbstractStringBuilder二者也都实现了java.io.Serializable, CharSequence接口

StringBuilder和StringBuffer最大的不同在于,StringBuilder的各个方法都不是线程安全的(不能同步访问),在多线程时可能存在线程安全问题,但StringBuilder的执行效率却比StringBuffer快的多。

2.StringBuilder的append过程

1)查看StringBuilder的append()方法

例如传入参数为int类型,返回的是this,在此并没有new一个新的对象

char[] value;
@Override
    public StringBuilder append(int i) {
        super.append(i);
        return this;
    }

2)查看super.append(i)方法

ensureCapacityInternal()确保字符数组长度足够,然后将i添加进字符数组中
仍返回的是this

public AbstractStringBuilder append(int i) {
        if (i == Integer.MIN_VALUE) {
            append("-2147483648");
            return this;
        }
        int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
                                     : Integer.stringSize(i);
        int spaceNeeded = count + appendedLength;
        ensureCapacityInternal(spaceNeeded);
        Integer.getChars(i, spaceNeeded, value);
        count = spaceNeeded;
        return this;
    }

3)查看ensureCapacityInternal()函数

传入的spaceNeeded参数为append后保存字符串的字符数组的长度。在函数中,如果如果原本的字符数组长度过短,就会执行Arrays.copyOf()重新开辟一个容量足够的内存空间,将字符数组复制进去,从新赋值给value

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

4)查看newCapacity(minimumCapacity)

其返回的int为新开辟空间的长度,一般为value.length*2+2,如果空间还不够,就直接将append后的长度赋值给newCapacity ,如果newCapacity 不合法(过大或者超过了Integer的最大值变为了负数),就返回hugeCapacity(minCapacity)函数所返回的合法的长度,newCapacity合法就返回newCapacity

MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
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;
    }

5)查看hugeCapacity(minCapacity),如果minCapacity过大,抛出异常,返回minCapacity 和 MAX_ARRAY_SIZE中的最大值

private int hugeCapacity(int minCapacity) {
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }

3.StringBuffer的append过程

1)查看StringBuffer的append()方法

toStringCache为新加入的内容的缓冲区
例如传入参数为int类型,返回的是this,在此并没有new一个新的对象

private transient char[] toStringCache;
char[] value;
@Override
    public synchronized StringBuffer append(int i) {
        toStringCache = null;
        super.append(i);
        return this;
    }

2)查看super.append(i)方法

ensureCapacityInternal()确保字符数组长度足够,然后将i添加进字符数组中
仍返回的是this

public AbstractStringBuilder append(int i) {
        if (i == Integer.MIN_VALUE) {
            append("-2147483648");
            return this;
        }
        int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
                                     : Integer.stringSize(i);
        int spaceNeeded = count + appendedLength;
        ensureCapacityInternal(spaceNeeded);
        Integer.getChars(i, spaceNeeded, value);
        count = spaceNeeded;
        return this;
    }

3)查看ensureCapacityInternal()函数

传入的spaceNeeded参数为append后保存字符串的字符数组的长度。在函数中,如果如果原本的字符数组长度过短,就会执行Arrays.copyOf()重新开辟一个容量足够的内存空间,将字符数组复制进去,从新赋值给value

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

4)查看newCapacity(minimumCapacity)

其返回的int为新开辟空间的长度,一般为value.length*2+2,如果空间还不够,就直接将append后的长度赋值给newCapacity ,如果newCapacity 不合法(过大或者超过了Integer的最大值变为了负数),就返回hugeCapacity(minCapacity)函数所返回的合法的长度,newCapacity合法就返回newCapacity

MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
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;
    }

5)查看hugeCapacity(minCapacity)

如果minCapacity过大,抛出异常,返回minCapacity 和 MAX_ARRAY_SIZE中的最大值

private int hugeCapacity(int minCapacity) {
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }

总结

StringBuffer和StringBuilder扩容机制的基本规则如下:

● 如果一次追加的字符长度超过了当前设置的容量,则会按照 当前容量*2+2 进行扩容;

● 如果一次追加的长度不仅超过了初始容量,而且按照 当前容量*2+2 扩容一次还不够,其容量会直接扩容到与所添加字符串长度相等的长度;

● 之后如果还要再追加新的字符内容,依然会按照 当前容量*2+2 进行扩容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值