Jim Blog I've been trying so hard,but doesn't even matter
博客信息

StringBuffer的扩容分析

发布时间:『 2018-05-15 13:39 』  博客类别:Java核心基础  阅读(89) 评论(0)

当我们需要大量拼接字符串的时候,如果使用String一个一个拼接,则会产生大量的String对象,造成性能下降,这个时候应该使用StringBuffer(线程安全)或StringBuilder(非线程安全)

以下分析基于jdk1.8StringBuffer源码里面很多方法都是直接调用的父类AbstractStringBuilder的方法,本文只关注核心代码:

StringBuffer内部为一个char数组,无参构造方法初始化容量为16,看StringBuffer的容量可以用StringBuffer.capacity()方法。很明显,作为一个需要扩容的容器,要是能预估要装的字符串大小,调用指定容量的构造方法,能一定程度提高性能。

当调用append方法时,会判断是否需要扩容,下面是append核心源码:

public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);  //判断是否需要扩容
        str.getChars(0, len, value, count);
        count += len;
        return this;
}

当需要扩容时,调用扩容方法,下面是扩容的源码:

/**
     * Returns a capacity at least as large as the given minimum capacity.
     * Returns the current capacity increased by the same amount + 2 if
     * that suffices.
     * Will not return a capacity greater than {@code MAX_ARRAY_SIZE}
     * unless the given minimum capacity is greater than that.
     *
     * @param  minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero or
     *         greater than Integer.MAX_VALUE
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2; //容量为原容量*2+2
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
}

     由于这几个类都是基于字符数组的,所以这个类的源码很容易看懂,StringBuffer的大部分方法都加了synchronized以确保线程安全,但牺牲了一定的性能。所以单线程下推荐使用StringBuilder。StringBuffer和StringBuilder这两个类可以说是AbstractStringBuilder类的线程安全和非线程安全实现,里面的方法大都是基于父类的方法实现。

关键字:   StringBuffer     StringBuilder  
博主信息
Jim
(生命,是一场徒劳的坚持)