关于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可能性越大。