Java中StringBuffer和StringBuilder扩容机制

本文详细剖析了Java中StringBuffer和StringBuilder的底层扩容原理,指出它们都源自AbstractStringBuilder,并揭示了初始容量和后续扩容策略。重点讲解了如何避免频繁扩容,以及它们之间的线程安全区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

了解一些java底层设计最直接最准确的的方法就是源码了。

StringBuffer和StringBuilder都继承自AbstractStringBuilder。jdk1.8中源码位于rt.jar/java/lang/路径下。

相关源码

初始的空闲容量都是16,当调用append方法时调用的都是super.append即AbstractStringBuilder中方法,所以扩容机制相同。

	// StringBuffer.java 
    public StringBuffer() {
        super(16);
    }
    
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
	//StringBuilder.java
	public StringBuilder() {
        super(16);
    }
    
	public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

通过append方法中的ensureCapacityInternal方法可以看出当追加后超出容量会触发扩容,通过newCapacity获得新容量。

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

计划扩容为2*n+2,n为扩容前容量,如果追加后长度超出则扩容为n+count,count为追加长度。由此可见下次append还会触发扩容机制。所以在设计时应该避免,最好能在初始时设置一个合理的容量。

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

最大容量为Integer.MAX_VALUE

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

另外还提供了方法用于用户测试调用的扩容方案,在追加超长字符串时可减少多次自动扩容的花销。

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

此外StringBuffer和StringBuilder的区别就在于StringBuffer的操作使用synchronized关键字加了锁,是线程安全的。

结论

StringBuffer和StringBuilder扩容都是通过共同父类AbstractStringBuilder实现的。

初始为len+16或自设置。后续扩容k>2*n+2?k:2*n+2

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值