本文参考这里
事先声明,本人小白,水平极低,请大佬绕行。
结论
长字符串拼接一定要用StringBuilder,而短字符串视情况而定,因为初始化StringBuilder貌似花费时间更大,所以如果是大量短字符串或许可以考虑直接用String拼接。
前情概括
优化他人代码时遇到使用String和+进行字符串拼接的情况,验证其与StringBuilder速度差异。结果发现和一直以来听说的不同,StringBuilder竟然比String直接拼接慢很多,具体测试过程见下。
测试过程
首先,按照我自己朴素的思维模式进行测试,大量短字符串:
public class BuilderTest {
private final String ORGEVAL_TABLE = "org_evaluation";
private final String EVALTABLE = "evalTable";
private final String ORG = "org";
private final String RATE = "rate";
private final String LEVEL = "level";
private final String NUMLEVEL = "numLevel";
private final String SUBMITTER = "submitter";
private final String SUBMITTIME = "submitTime";
public static void main(String[] args) {
BuilderTest builderTest = new BuilderTest();
//小插曲,之前用nanoTime()测试单次字符串拼接时间比较的时候,如果不先使用一下nanoTime(),第一个被调用的方法就会比第二个慢……
builderTest.preDo();
builderTest.test();
builderTest.test1();
}
void preDo(){
Long start = System.nanoTime();
double pi=Math.PI;
for(int i=0;i<1000;i++){
pi=Math.pow(pi,2);
pi=Math.sqrt(pi);
}
System.out.println(pi);
System.out.println("没用的计算用时:" + (System.nanoTime() - start));
}
void test() {
Long start = System.currentTimeMillis();
for(int i=0;i<1000000;i++) {
String ORGEVAL_TABLE = "org_evaluation";
String EVALTABLE = "evalTable";
String ORG = "org";
String RATE = "rate";
String LEVEL = "level";
String NUMLEVEL = "numLevel";
String SUBMITTER = "submitter";
String SUBMITTIME = "submitTime";
String sql = "UPDATE " +
ORGEVAL_TABLE + " SET " +
EVALTABLE + " = ?," +
ORG + " = ?," +
RATE + " = ?," +
LEVEL + " = ?," +
NUMLEVEL + " = ?," +
SUBMITTER + " = ?," +
SUBMITTIME + " = ? WHERE ID = ? ";
}
System.out.println("直接拼接用时:" + (System.currentTimeMillis() - start));
}
void test1() {
Long start = System.currentTimeMillis();
for(int i=0;i<1000000;i++) {
StringBuilder sb = new StringBuilder();
sb.append("UPDATE ");
sb.append(ORGEVAL_TABLE);
sb.append(" SET ");
sb.append(EVALTABLE);
sb.append(" = ?,");
sb.append(ORG);
sb.append(" = ?,");
sb.append(RATE);
sb.append(" = ?,");
sb.append(LEVEL);
sb.append(" = ?,");
sb.append(NUMLEVEL);
sb.append(" = ?,");
sb.append(SUBMITTER);
sb.append(" = ?,");
sb.append(SUBMITTIME);
sb.append(" = ? WHERE ID = ?");
}
System.out.println("StringBuilder用时:" + (System.currentTimeMillis() - start));
}
}
结果是:
3.141592653589793
没用的计算用时:888100
直接拼接用时:114
StringBuilder用时:186
而当循环次数较少的时候,比如将循环次数改为10000:
3.141592653589793
没用的计算用时:883800
直接拼接用时:15
StringBuilder用时:5
此时StringBuilder已经比直接拼接快了(试了几次都是这样,应该不是误差问题)。
相比之下,如果是长字符串,即:
void test() {
Long start = System.currentTimeMillis();
String sql="";
//这里改成10000已经够慢了,不敢再加了
for(int i=0;i<10000;i++) {
sql += "UPDATE " +
ORGEVAL_TABLE + " SET " +
EVALTABLE + " = ?," +
ORG + " = ?," +
RATE + " = ?," +
LEVEL + " = ?," +
NUMLEVEL + " = ?," +
SUBMITTER + " = ?," +
SUBMITTIME + " = ? WHERE ID = ? ";
sql+=i;
}
System.out.println("直接拼接用时:" + (System.currentTimeMillis() - start));
}
void test1() {
Long start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for(int i=0;i<10000;i++) {
sb.append("UPDATE ");
sb.append(ORGEVAL_TABLE);
sb.append(" SET ");
sb.append(EVALTABLE);
sb.append(" = ?,");
sb.append(ORG);
sb.append(" = ?,");
sb.append(RATE);
sb.append(" = ?,");
sb.append(LEVEL);
sb.append(" = ?,");
sb.append(NUMLEVEL);
sb.append(" = ?,");
sb.append(SUBMITTER);
sb.append(" = ?,");
sb.append(SUBMITTIME);
sb.append(" = ? WHERE ID = ?");
sb.append(i);
}
// sb.toString();
System.out.println("StringBuilder用时:" + (System.currentTimeMillis() - start));
}
结果是:
3.141592653589793
没用的计算用时:909700
直接拼接用时:9307
StringBuilder用时:5
此时StringBuilder明显已经优于直接拼接。
小插曲
之前用nanoTime()测试单次字符串拼接时间比较的时候,如果不先使用一下nanoTime(),第一个被调用的方法就会比第二个慢……不知道原因是什么
如下:
public class BuilderTest {
private final String ORGEVAL_TABLE = "org_evaluation";
private final String EVALTABLE = "evalTable";
private final String ORG = "org";
private final String RATE = "rate";
private final String LEVEL = "level";
private final String NUMLEVEL = "numLevel";
private final String SUBMITTER = "submitter";
private final String SUBMITTIME = "submitTime";
public static void main(String[] args) {
BuilderTest builderTest = new BuilderTest();
builderTest.test1();
builderTest.test();
}
void test() {
Long start = System.nanoTime();
String sql = "";
sql = "UPDATE " +
ORGEVAL_TABLE + " SET " +
EVALTABLE + " = ?," +
ORG + " = ?," +
RATE + " = ?," +
LEVEL + " = ?," +
NUMLEVEL + " = ?," +
SUBMITTER + " = ?," +
SUBMITTIME + " = ? WHERE ID = ? ";
System.out.println("直接拼接用时:" + (System.nanoTime() - start));
}
void test1() {
Long start = System.nanoTime();
StringBuilder sb = new StringBuilder();
sb = new StringBuilder();
sb.append("UPDATE ");
sb.append(ORGEVAL_TABLE);
sb.append(" SET ");
sb.append(EVALTABLE);
sb.append(" = ?,");
sb.append(ORG);
sb.append(" = ?,");
sb.append(RATE);
sb.append(" = ?,");
sb.append(LEVEL);
sb.append(" = ?,");
sb.append(NUMLEVEL);
sb.append(" = ?,");
sb.append(SUBMITTER);
sb.append(" = ?,");
sb.append(SUBMITTIME);
sb.append(" = ? WHERE ID = ?");
// sb.toString();
System.out.println("StringBuilder用时:" + (System.nanoTime() - start));
}
}
结果:
StringBuilder用时:141900
直接拼接用时:4300
而单纯将main中test和test1的顺序调换一下之后,结果是:
直接拼接用时:119200
StringBuilder用时:6400
怀疑是nano用之前需要初始化一下?加了preDo()之后正常了,即:
3.141592653589793
没用的计算用时:1164700
直接拼接用时:8000
StringBuilder用时:6000