XxwGit 的个人博客

记录精彩的程序人生

目录
StringBuilder和StringBuffer的扩容机制
/  

StringBuilder和StringBuffer的扩容机制

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

该方法是用来确保容量至少等于指定的最小值,是该类的核心也是其两个实现类StringBuffer和StringBuilder的核心。通过这种方式来实现数组的动态扩容。下面来看下其具体逻辑。

  1. 判断入参minimumCapacity是否有效,即是否大于0,大于0执行ensureCapacityInternal方法,小于等于0则忽略。
private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
  1. 判断入参容量值是否比原容量大,如果大于原容量,执行扩容操作,实际上就是创建一个新容量的数组,然后再将原数组中的内容拷贝到新数组中,如果小于或等于原容量则忽略。
private static final int 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;
    }
  1. 计算新数组的容量大小,新容量取原容量的2倍加2和入参minCapacity中较大者。然后再进行一些范围校验。新容量必需在int所支持的范围内,之所以有<=0判断是因为,在执行 (value.length << 1) + 2操作后,可能会出现int溢出的情况。如果溢出或是大于所支持的最大容量(MAX_ARRAY_SIZE为int所支持的最大值减8),则进行hugeCapacity计算,否则取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;
    }
  1. 这一步先进行范围检查,必须在int所支持的最大范围内。然后在minCapacity与MAX_ARRAY_SIZE之间取较大者,此方法取的范围是Integer.MAX_VALUE - 8到Integer.MAX_VALUE之间的范围。
  2. 总结
    • 通过value = Arrays.copyOf(value,newCapacity(minimumCapacity));进行扩容
    • 新容量取 minCapacity,原容量乘以2再加上2中较大的,但不能大于int所支持的最大范围。
    • 在实际环境中在容量远没达到MAX_ARRAY_SIZE的时候就报OutOfMemoryError异常了,其实就是在复制的时候创建了数组char[] copy = new char[newLength];这里支持不了那么大的内存消耗,可以通过 -Xms256M -Xmx768M设置最大内存。


标题:StringBuilder和StringBuffer的扩容机制
作者:XxwGit
地址:http://xxwgit.cn/solo/articles/2019/09/06/1567759674059.html

评论