实例6 - StringBuilder和StringBuffer
2018-12-28 本文已影响0人
静筱
字符操作是Java代码中最高频的操作,因此字符操作的效率极大地影响程序本身的效率。
Java中字符操作可使用StringBuilder(线程不安全),StringBuffer(线程安全)以及String.
其中String值不可变,因此在字符操作比如字符串拼接,截取等等,底层JVM处理时,实际上都会创建一个新的String对象,消耗额外资源。
因此在高频字符操作时,我们一般改为StringBuffer或者 StringBuilder进行操作,而处理完的结果再通过String返回。(详见<a href="">asdoifjew</a>)
StringBuilder和StringBuffer转成String有两种方式:
-
new String(StringBuilder sbd) 或 new String(StringBuffer sbr)
-
StringBuilder和StringBuffer本身的toString()方法
这两种方法的效率又如何呢?哪种效率更高呢?
下面我们通过一个实例来测试一下:
public class StringOperationTest {
private StringBuilder getStringBuilder(){
StringBuilder sbr = new StringBuilder();
for(int i=0;i<10000; i++){
sbr.append("Test");
}
return sbr;
}
private StringBuffer getStringBuffer(){
StringBuffer sbr = new StringBuffer();
for(int i=0;i<10000; i++){
sbr.append("Test");
}
return sbr;
}
public static void main(String[] args){
int k=1000;
long max1 = 0;
long max2 = 0;
long max3 = 0;
long max4 = 0;
long min1 = 0;
long min2 = 0;
long min3 = 0;
long min4 = 0;
long sum1 = 0;
long sum2 = 0;
long sum3 = 0;
long sum4 = 0;
for(int j=0 ; j<=k; j++) {
StringOperationTest soTest = new StringOperationTest();
long start = System.currentTimeMillis();
String test1 = soTest.getStringBuffer().toString();
long start2 = System.currentTimeMillis();
String test2 = soTest.getStringBuilder().toString();
long start3 = System.currentTimeMillis();
String test3 = new String(soTest.getStringBuffer());
long start4 = System.currentTimeMillis();
String test4 = new String(soTest.getStringBuilder());
long time1=System.currentTimeMillis()-start;
long time2=System.currentTimeMillis()-start2;
long time3=System.currentTimeMillis()-start3;
long time4=System.currentTimeMillis()-start4;
if(time1>max1){
max1 = time1;
}
if(time2>max2){
max2 = time2;
}
if(time3>max3){
max3 = time3;
}
if(time4>max4){
max4 = time4;
}
if(time1<max1){
min1 = time1;
}
if(time2<max2){
min2 = time2;
}
if(time3<max3){
min3 = time3;
}
if(time4<max4){
min4 = time4;
}
sum1+=time1;
sum2+=time2;
sum3+=time3;
sum4+=time4;
}
long avg1 = (long)sum1/k;
long avg2 = (long)sum2/k;
long avg3 = (long)sum3/k;
long avg4 = (long)sum4/k;
System.out.println("StringBuffer.toString:[max]"+max1+"ms, [min]"+min1+"ms, [avg]"+avg1+"ms");
System.out.println("StringBuilder.toString:[max]"+max2+"ms, [min]"+min2+"ms, [avg]"+avg2+"ms");
System.out.println("new String(StringBuffer):[max]"+max3+"ms, [min]"+min3+"ms, [avg]"+avg3+"ms");
System.out.println("new String(StringBuilder):[max]"+max4+"ms, [min]"+min4+"ms, [avg]"+avg4+"ms");
}
}
结果
StringBuffer.toString:[max]18ms, [min]2ms, [avg]1ms
StringBuilder.toString:[max]17ms, [min]2ms, [avg]1ms
new String(StringBuffer):[max]11ms, [min]1ms, [avg]0ms
new String(StringBuilder):[max]10ms, [min]0ms, [avg]0ms
从平均耗时来看StringBuffer.toString 和StringBuilder.toString一样,比String构造函数略慢。
从最大耗时来看,
StringBuffer.toString 耗时最多,其次是StringBuilder.toString, new String(StringBuffer), 最好的是new String(StringBuilder)
其中
//String类:
public String(StringBuffer var1) {
String var2 = var1.toString();//此处调用的是StringBuffer和toString()方法,是线程安全的
this.value = var2.value;
this.count = var2.count;
this.offset = var2.offset;
}
//StringBuffer类:
public synchronized String toString() {
return new String(this.value, 0, this.count);
}
综合来说
多线程开发,用StringBuffer,转成String时,用new String(StringBuffer sbr);
StringBuilder转成String时,用new String(StringBuilder sbe)