关于String, StringBuffer, StringBuilder在拼接字符串时的执行效率,网上已经有很多文章介绍了,这里我实际测了一下,可总结为:
String.concat > StringBuilder > StringBuffer > String+=
注:
(1)此处的String+=不是在编译期
(2)StringBuilder > StringBuffer这个在单线程下也不是绝对的
实际代码:
package string;
/**
*
* String和StringBuffer和StringBuilder的执行效率比较
*
*
*/
public class StringBuffer_VS_String_Efficiency {
static int times = 20000;//循环次数
// static int times = 200000;//循环次数
// static int times = 2000000;//循环次数
/**
*
* String+=
*/
public static void StringTest(String s){
String str = "";
long startTime = System.currentTimeMillis();
for(int i=0;i<times/100;i++){
str += s;
}
long endTime = System.currentTimeMillis();
System.out.println("String+=所用的时间:"+ (endTime - startTime));
}
/**
* String+=的实际执行过程(jdk1.5以上版本会做优化)
* str += "here";可以等同于
* StringBuilder sb = new StringBuilder(str);
* sb.append("here");
* str = sb.toString();
*/
public static void StringTest2(String s){
String str = "";
long startTime = System.currentTimeMillis();
for(int i=0;i<times/100;i++){
StringBuilder sb = new StringBuilder(str);
sb.append(s);
str = sb.toString();
}
long endTime = System.currentTimeMillis();
System.out.println("String+=的实际执行过程所用的时间:"+ (endTime - startTime));
}
/**
* String.concat()
* 是利用Char[]拼接起来的(新建String对象)
*/
public static void StringConcatTest(String s){
String str = "";
long startTime = System.currentTimeMillis();
for(int i=0;i<times;i++){
str.concat(s);
}
long endTime = System.currentTimeMillis();
System.out.println("String.concat方法所用的时间:"+ (endTime - startTime));
}
/**
* StringBuffer
* append方法也是利用Char[]拼接起来的(没有新建String对象,
* 每次扩容至(value.length + 1) * 2)
*/
public static void StringBufferTest(String s){
StringBuffer sb = new StringBuffer();
long startTime = System.currentTimeMillis();
for(int i=0;i<times;i++){
sb.append(s);
}
String s1 = sb.toString();
long endTime = System.currentTimeMillis();
System.out.println("StringBuffer所用的时间:"+ (endTime - startTime));
}
/**
* StringBuilder
* append方法和StringBuffer中是一样的内容
*/
public static void StringBuilderTest(String s){
StringBuilder sb = new StringBuilder();
long startTime = System.currentTimeMillis();
for(int i=0;i<times;i++){
sb.append(s);
}
String s1 = sb.toString();
long endTime = System.currentTimeMillis();
System.out.println("StringBuilder所用的时间:"+ (endTime - startTime));
}
public static void main(String[] args){
String s = "asdfghhjkqwerty";
StringTest(s);
StringTest2(s);
StringConcatTest(s);
StringBufferTest(s);
StringBuilderTest(s);
}
}
注:由于循环次数太大,而String +=的执行时间太慢,所以让String +=的循环次数改为了times/100,就这样,起执行时间还是比StringBuffer, StringBuilder要长的多
运行结果:
1. times = 20000;//循环次数 时:
String+=所用的时间:0
String+=的实际执行过程所用的时间:0
String.concat方法所用的时间:0
StringBuffer所用的时间:0
StringBuilder所用的时间:16
2. times = 200000;//循环次数 时:
String+=所用的时间:78
String+=的实际执行过程所用的时间:62
String.concat方法所用的时间:16
StringBuffer所用的时间:31
StringBuilder所用的时间:47
3. times = 2000000;//循环次数 时:
String+=所用的时间:10047
String+=的实际执行过程所用的时间:10171
String.concat方法所用的时间:125
StringBuffer所用的时间:391
StringBuilder所用的时间:266
结果分析:
(1)结果1中由于循环次数不算太大,String+=的循环次数也只是times/100,所以会出现string+=的执行时间为0,而在结果2,3中,即便是String+=循环的次数只有 StringBuilder 和StringBuffer的百分之一,其执行效率也是远不如后二者;
(2)综合1,2中的结果来看,在循环次数不算太大的情况下,执行效率:StringBuilder < StringBuffer;
而在结果3中, 执行效率:StringBuilder > StringBuffer; 所以单线程下StringBuilder
和StringBuffer的执行效率也不是绝对确定的。
(3)综合以上结果中,String.concat()方法的执行效率是最高的,但是由于这个方法中每次都是创建一个新的字符串,丢弃原来的字符串,所以垃圾收集的压力会较大。
其源代码如下:
public String concat(String s)
{
int i = s.length();
if(i == 0)
{
return this;
} else
{
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
(4)关于StringBuilder 和StringBuffer的执行效率的比较,为了不受其他方法影响,在main()方法中注释掉了其他方法,又单独比较了下这两个方法
public static void main(String[] args){
String s = "asdfghhjkqwerty";
// StringTest(s);
// StringTest2(s);
// StringConcatTest(s);
StringBufferTest(s);
StringBuilderTest(s);
}
结果发现在循环次数分别为万、十万、百万这几个数量级上,两者的执行效率还是不绝对确定,每次执行结果都可能不一样,结果规律是:循环次数越大,StringBuilder体现出的效率就越高,StringBuilder >StringBuffer可能性越大。