区别
其实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的内存扩充。