关于StringBuilder的几点
1.在初始化的时候,可以加或不加参数
//无参
StringBuilder sb=new StringBuilder();
//有参
StringBuilder sb1=new StringBuilder("hello");
StringBuilder sb2=new StringBuilder(15);
无参:默认分配容量为16。也就是调用了父类生成了一个大小为16的数组。
有参:sb1在初始化时赋值了一个hello字符串。sb2在初始化时指定了capacity的大小为15.
//在源码中是这么写的(StringBuilder.class)
public StringBuilder() {
super(16);
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder(int capacity) {
super(capacity);
}
而在AbstractStringBuilder的源码中可以是这么写的
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
也就是说,当StringBuilder初始化时带参数时,如果带的是int型参数,会调用父类中的构造函数然后执行value = new char[capacity];如果带的是String型参数,还是会先调用父类中的构造函数value = new char[capacity];然后再调用append(str)的方法,将String型的参数放入到数组中。
2.StringBuilder.append()
先看源码
StringBuilder.class
public StringBuilder append(String str) {
super.append(str);
return this;
}
AbstractStringBuilder.class
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;
}
当调用StringBuilder.append(str)方法时,调用其父类中的方法。若str不为空,执行ensureCapacityInternal(count + len)方法,在此方法中,会判断append之后的字符串长度,若比原来开辟的空间要大,则需要另外开辟新的更大的空间,并将原来的value值复制进去。执行完后回来执行str.getChars(0, len, value, count),将str的值复制到数组value中,存放位置为value数组的第count位开始存放,也就是跟在原始数据的后面。简单来说,StringBuilder的工作流程,首先在初始化时,自动分配大小为16的一个数组来存放数据。当再次往其中存放数据时,会判断原来的数组大小够不够,若不够,重新开一个更大的数据并将原始数据存入,然后将需要添加的数据存到原始数据后面。
3.append与“+”的区别
根据上面说的StringBuilder每次append会判断原始的数组是否够存,如果够存,会将新的数据存到原始的数组中。而+,每次+都会生成一个新的String对象(String对象一旦建立是无法更改的。)这样以来,如果做大量的字符拼接工作时,append的优势就会体现的很明显了。
4.StringBuilder与StringBuffer
在jdk1.5之前,用户对于字符串的操作无非是String与StringBuffer。但在1.5中加入了StringBuilder这个新的类。它和StringBuffer的原理和操作基本一样。但StringBuilder不是线程安全的,不适合对于多线程的使用。StringBuffer是多线程的,适合于多线程的使用。在单线程中使用时,优先选择StringBuilder。
long tt=500000;
StringBuilder sBuilder=new StringBuilder();
StringBuffer sBuffer=new StringBuffer();
long start=System.currentTimeMillis();
for(long i=1;i<tt;i++){
sBuilder.append("add");
}
long end=System.currentTimeMillis();
System.out.println("StringBuilder所用时间"+(end-start));
start=System.currentTimeMillis();
for(long i=1;i<tt;i++){
sBuffer.append("add");
}
end=System.currentTimeMillis();
System.out.println("StringBuffer所用时间"+(end-start));
运行结果
StringBuilder所用时间23
StringBuffer所用时间31
可以验证,在单线程的使用中,StringBuilder的效率更高。