String拼接和StringBuilder性能比较问题

String拼接和StringBuilder性能比较问题

本文参考这里
事先声明,本人小白,水平极低,请大佬绕行。

结论

长字符串拼接一定要用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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值