作String拼接时用StringBuilder(或StringBuffer)好仍是直接用+号性能好?通常来讲是前者,不过也有用加号略好的时候。
首先我一直认为用+号有很好的可读性,并且当String拼接在一个等式时,即形如
String s = “abc” + s2 + s3
jdk的实现原理也是转换为一个StringBuilder并一直append,效率也是差不太多的,因此我是比较喜欢在无循环或条件分支代码的状况下全使用String相加,若是有循环或分支,就是写成这样:java
StringBuilder hql =newStringBuilder(“select…………..”
+“ from”
+” where”);
If(xxxx){
Hql.append(“xxxx”);
}web
不过你们的代码通常都是全append方式,代码一写能够写出几百行,写的时候很差写,改的时候很差读,真有点看不过去了。
今天特别对两种拼接方式作了一下测试,来给你们一个参考。
找到项目中一个约200行的hql拼接,将append全转化为+号,如图sql
publicstaticvoid testStringJoin(){
TestStringJoin instance =newTestStringJoin();
longbegin, elapse;
begin=System.currentTimeMillis();
int execTimes =10000;
for(int i =0; i < execTimes; i++){
instance.testStringJoinWithPlus();
}
elapse =System.currentTimeMillis()-begin;
System.out.println("testStringJoinWithPlus "+ execTimes
+" times elapse = "+ elapse +"ms");
begin=System.currentTimeMillis();
for(int i =0; i < execTimes; i++){
instance.testStringJoinWithStringBuilder();
}
elapse =System.currentTimeMillis()-begin;
System.out.println("testStringJoinWithStringBuilder "+ execTimes
+" times elapse = "+ elapse +"ms");
}app
结果:
testStringJoinWithPlus 10000 times elapse = 77ms
testStringJoinWithStringBuilder 10000 times elapse = 151ms (这里有StringBuilder扩容问题,见下面继续分析)函数
基本上可保持后者约为前者2倍时间的状况,也就是说,用StringBuilder拼接字符串有时候还不如直接用+号拼接。
为啥呢?对比了一下两方法的中间代码,只取一小段就能够看出问题了
用StringBuilder拼接字符串的方式:性能
Code:
0:new#2; //class java/lang/StringBuilder
3: dup
4: sipush 5000
7: invokespecial #3; //Method java/lang/StringBuilder."<init>":(I)V
10: astore_1
11: aload_1
12: ldc #4; //String SELECT
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: pop
18: aload_1
19: ldc #6; //String new map(
21: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: pop
25: aload_1
26: ldc #7; //String corp.id AS corpId,
28: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
31: pop测试
Code:
0:new#2; //class java/lang/StringBuilder
3: dup
4: invokespecial #85; //Method java/lang/StringBuilder."<init>":()V
7: ldc #86; //String SELECT new map( corp.id AS corpId, ( SELECT COUNT(*) FROM TPerson per, TXXJL jl WHERE per.CBh = jl.CBhPerson AND per.corpId = corp.id AND jl.CSJYJ IS NULL AND( jl.NSpcz = ? OR jl.NSpcz = ? OR( jl.NSpcz = ? AND jl.NSpjg = ? ) OR( jl.NSpcz = ? AND jl.NSpjg = ? ) ) AND( jl.CJdyj IS NULL OR jl.CJdyj = ? ) AND jl.CBh NOT IN( SELECT pctq.CBhJlxx FROM TXXPctq pctq, TXXPcxx pcxx WHERE pctq.CBhPcxx = pcxx.CBh AND pcxx.NLx = ? AND pcxx.CCjdw = corp.id ) )AS dcs, ( SELECT COUNT(*) FROM TPerson per, TXXJL jl WHERE per.CBh = jl.CBhPerson AND per.corpId = corp.id AND jl.CJdyj IS NULL AND( jl.NSpcz = ? OR jl.NSpcz = ? OR( jl.NSpcz = ? AND jl.NSpjg = ? ) OR( jl.NSpcz = ? AND jl.NSpjg = ? ) ) AND( jl.CSJYJ IS NULL OR jl.CSJYJ = ? ) AND jl.CBh NOT IN( SELECT pctq.CBhJlxx FROM TXXPctq pctq, TXXPcxx pcxx WHERE pctq.CBhPcxx = pcxx.CBh AND pcxx.NLx = ? AND pcxx.CCjdw = corp.id ) )AS dyyjd, ( SELECT COUNT(*) FROM TPerson per, TXXJL jl WHERE per.CBh = jl.CBhPerson AND per.corpId = corp.id AND( jl.CSJYJ = ? AND jl.CJdyj = ? ) AND( jl.NSpcz = ? OR jl.NSpcz = ? OR( jl.NSpcz = ? AND jl.NSpjg = ? ) OR( jl.NSpcz = ? AND jl.NSpjg = ? ) ) AND jl.CBh NOT IN( SELECT pctq.CBhJlxx FROM TXXPctq pctq, TXXPcxx pcxx WHERE pctq.CBhPcxx = pcxx.CBh AND pcxx.NLx = ? AND pcxx.CCjdw = corp.id ) )AS dfpqc, ( SELECT COUNT(*) FROM TXXJL jl, TZf zfxx, TXXPctq pctq WHERE jl.CBhPerson = zfxx.CBh AND pctq.CBhJlxx = jl.CBh AND pctq.CBhPcxx = ? AND jl.NSpzt = ? AND jl.NSpcz != ? AND zfxx.corpId = corp.id )AS dspbw, ( SELECT COUNT(DISTINCT pt.CBhJlxx) FROM TXXPctq pt, TXXJL tq, TPerson per, TXXPcxx pc WHERE pc.NLx =? AND pc.CCjdw = corp.id AND pt.CBhJlxx = tq.CBh AND tq.CBhPerson = per.CBh AND pt.CBhPcxx = pc.CBh AND per.NSfyx =? AND per.NSfyx =
9: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: getstatic #87; //Field SF_YES:Ljava/lang/Integer;
15: invokevirtual #88; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
18: ldc #66; //String AND tq.NTqlb IS NOT NULL
20: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: ldc #67; //String AND tq.NSpzt >= ?
25: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: ldc #68; //String AND tq.NSpzt <=?
30: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;优化
+" AND per.NSfyx = "+TestStringJoin.SF_YESui
由于字符串+号拼接时若是不出现变量、非字符串常量的时候,编译期就直接认为是一个字符串了,同时由于有字符串缓冲池的存在,
Code:
0:new#2; //class java/lang/StringBuilder
3: dup
4: invokespecial #85; //Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: aload_1
9: ldc #90; //String SELECT new map(corp.id AS corpId, (SELECT COUNT(*) FROM TPerson per, TXXJL jl WHERE per.CBh = jl.CBhPerson AND per.corpId = corp.id AND jl.CSJYJ IS NULL AND (jl.NSpcz = ? OR jl.NSpcz = ? OR (jl.NSpcz = ? AND jl.NSpjg = ?) OR (jl.NSpcz = ? AND jl.NSpjg = ?)) AND (jl.CJdyj IS NULL OR jl.CJdyj = ?) AND jl.CBh NOT IN (SELECT pctq.CBhJlxx FROM TXXPctq pctq, TXXPcxx pcxx WHERE pctq.CBhPcxx = pcxx.CBh AND pcxx.NLx = ? AND pcxx.CCjdw = corp.id)) AS dcs, (SELECT COUNT(*) FROM TPerson per, TXXJL jl
11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: pop
15: aload_1
16: ldc #91; //String WHERE per.CBh = jl.CBhPerson AND per.corpId = corp.id AND jl.CJdyj IS NULL AND (jl.NSpcz = ? OR jl.NSpcz = ? OR (jl.NSpcz = ? AND jl.NSpjg = ?) OR (jl.NSpcz = ? AND jl.NSpjg = ?)) AND (jl.CSJYJ IS NULL OR jl.CSJYJ = ?) AND jl.CBh NOT IN (SELECT pctq.CBhJlxx FROM TXXPctq pctq, TXXPcxx pcxx WHERE pctq.CBhPcxx = pcxx.CBh AND pcxx.NLx = ? AND pcxx.CCjdw = corp.id)) AS dyyjd, (SELECT COUNT(*) FROM TPerson per, TXXJL jl WHERE per.CBh = jl.CBhPerson AND per.corpId = corp.id AND (jl.CSJYJ = ? AND jl.CJdyj = ?) AND (jl.NSpcz = ? OR jl.NSpcz = ? OR (jl.NSpcz = ? AND jl.NSpjg = ?) OR (jl.NSpcz = ? AND jl.NSpjg = ?)) AND jl.CBh NOT IN (SELECT pctq.CBhJlxx FROM TXXPctq pctq, TXXPcxx pcxx WHERE pctq.CBhPcxx = pcxx.CBh AND pcxx.NLx = ? AND pcxx.CCjdw = corp.id)) AS dfpqc, (SELECT COUNT(*) FROM TXXJL jl, TZf zfxx, TXXPctq pctq WHERE jl.CBhPerson = zfxx.CBh AND pctq.CBhJlxx = jl.CBh AND pctq.CBhPcxx = ? AND jl.NSpzt = ? AND jl.NSpcz != ? AND zfxx.corpId = corp.id) AS dspbw, (SELECT COUNT(DISTINCT pt.CBhJlxx) FROM TXXPctq pt, TXXJL tq, TPerson per, TXXPcxx pc WHERE pc.NLx = ? AND pc.CCjdw = corp.id AND pt.CBhJlxx = tq.CBh AND tq.CBhPerson = per.CBh AND pt.CBhPcxx = pc.CBh AND per.NSfyx = ? AND per.NSfyx = 1 AND tq.NTqlb IS NOT NULL AND tq.NSpzt >= ? AND tq.NSpzt <= ? AND tq.NSpcz = ? AND tq.NSpjg = ?) AS tbcl, (SELECT COUNT(DISTINCT pt.CBhJlxx) FROM TXXPcxx pc, TXXPctq pt, TXXJL tq, TZf zf WHERE pc.NLx = ? AND pc.CCjdw = corp.id AND pt.CBhJlxx = tq.CBh AND tq.CBhPerson = per.CBh AND pt.CBhPcxx = pc.CBh AND per.NSfyx = ? AND tq.NTqlb IS NOT NULL AND ((tq.NSpzt >= ? AND tq.NSpzt <= ? AND tq.NSpcz = ? AND tq.NSpjg = ?) O (tq.NSpzt = ? AND tq.NSpcz >= ?))) AS djwzx) FROM XfzxCorp corp
18: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: pop
22: aload_1
23: invokevirtual #84; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: areturnspa