对比
String是不可变对象,类中的char数组定义为final,一旦创建就无法改变。a+b操作是通过StringBuilder的append来拼接a和b,所以存在很多的+操作的时候会生成许多的StringBuilder来拼接。
StringBuilder和StringBuffer里面的char数组都是可变的。允许进行扩容。不同之处是StringBuffer是线程安全的、StringBuilder是非线程安全的。
StringBuilder
/**
* 这个数组记录内容.
*/
char[] value;
append
/**
*StringBuilder
*/
public StringBuilder append(String str) {
super.append(str);
return this;
}
/**
*AbstractStringBuilder
*/
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;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity);
}
void 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);
}
如果char数组长度还够存储则无须扩容,若不够则通过copyOf函数扩容并复制。
以下为个人观点
创建一个新的字符数组并拷贝需要耗费一定的时间,如何能够做到零拷贝。借鉴与Netty的BufByte。
/**
*简单实例(没有完全实现)
*/
/**
* @Author Joker
* @Description
* @Date Create in 下午1:30 2018/3/25
*/
public class CharsDecorate {
private int length;
private int index;
private char[] chars;
public CharsDecorate(String s) {
chars = s.toCharArray();
length = s.length();
index = s.length();
}
public int getLength() {
return length;
}
public int getIndex() {
return index;
}
public char[] getChars() {
return chars;
}
}
import java.util.List;
/**
* @Author Joker
* @Description
* @Date Create in 下午1:30 2018/3/25
*/
public abstract class JokerAbstractStringBuilder {
List<CharsDecorate> cs;
int length;
public JokerAbstractStringBuilder append(String s) {
CharsDecorate c = new CharsDecorate(s);
cs.add(c);
return this;
}
}
实现了零拷贝
StringBuffer
StringBuffer与StringBuilder类似,区别在于StringBuffer是线程安全的类。