StringBuilder和StringBuffer区别以及原理

区别

其实StringBuilder和StringBuffer用法都是一样,几乎没啥区别,我比较常用StringBuilder。但是说它们之间到底有没有区别,那肯定是有的。StringBuffer的大多数方法都是用synchronized 修饰的,所以StringBuffer是线程安全的,但是就因为它被修饰了,所以StringBuffer的效率也是比StringBuilder底的。

StringBuilder原理

要研究一下StringBuilder的原理就要先看看StringBuilder的源码。

StringBuilder的定义,它定义了char的数组,这个数组长度是可变,它的长度就是count

char[] value;
int count;

先new个StringBuilder对象

StringBuilder sb = new StringBuilder();

StringBuilder的构造方法,默认就是创建16的字符数组,也就是16个字节的大小

  public StringBuilder() {
        super(16);
    }

    public StringBuilder(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

StringBuilder的append的方法

    private StringBuilder append(StringBuilder sb) {
        if (sb == null)
            return append("null");
        int len = sb.length();
        int newcount = count + len;
        if (newcount > value.length)
            expandCapacity(newcount);
        sb.getChars(0, len, value, count);
        count = newcount;
        return this;
    }

当append字符串的时候,首先会判断sb是否为空,如果不为空就获取sb的长度和StringBuilder已经拼接的字符串长度之和,也就是newcount,如果newcount大于了字符串数组(value)的长度,那么就使用expandCapacity扩充容量。最后使用sb.getChars()将新添加的字符串添加到字符串数组(value)中,并将newcount的值赋予count。

private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0)
        expandCapacity(minimumCapacity);
}

ensureCapacityInternal方法又调用了expandCapacity方法

oid expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

先扩充16*2+2字节的容量(34字节),然后判断新扩充的字节是否大于StringBuilder的拼接字符串的长度(新添加的+已经有的字符串的长度),如果小于的话,那么新扩充的长度newCapacity就赋予StringBuilder的拼接的字符串的长度。如果newCapacity<0说明oom异常了(内存不够用了),那么这时候newCapacity = Integer.MAX_VALUE。最后在把字符串数组value的内存扩充。

你可能感兴趣的:(StringBuilder和StringBuffer区别以及原理)