1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        StringBuider 在什么條件下使用效率更高?

        共 559字,需瀏覽 2分鐘

         ·

        2020-07-30 18:09

        Java技術(shù)棧

        www.javastack.cn

        關(guān)注閱讀更多優(yōu)質(zhì)文章


        引言

        都說(shuō) StringBuilder 在處理字符串拼接上效率要強(qiáng)于 String,但有時(shí)候我們的理解可能會(huì)存在一定的偏差。

        最近我在測(cè)試數(shù)據(jù)導(dǎo)入效率的時(shí)候就發(fā)現(xiàn)我以前對(duì) StringBuilder 的部分理解是錯(cuò)誤的。后來(lái)我通過(guò)實(shí)踐測(cè)試 + 找原理 的方式搞清楚了這塊的邏輯?,F(xiàn)在將過(guò)程分享給大家

        測(cè)試用例

        我們的代碼在循環(huán)中拼接字符串一般有兩種情況

        對(duì)于這兩種情況,我創(chuàng)建了兩個(gè)對(duì)照組

        第一組:

        在每次 For 循環(huán)中拼接字符串,即拼即用、用完即毀。分別使用 String 和 StringBuilder 拼接

        /**
        ?*?循環(huán)內(nèi)?String?拼接字符串,一次循環(huán)后銷(xiāo)毀
        ?*/
        public?static?void?useString(){
        ????for?(int?i?=?0;?i?????????String?str?=?str1?+?i?+?str2?+?i?+?str3?+?i?+?str4?;
        ????}
        }

        /**
        ?*?循環(huán)內(nèi)?使用?StringBuilder?拼接字符串,一次循環(huán)后銷(xiāo)毀
        ?*/
        public?static?void?useStringBuilder(){
        ????for?(int?i?=?0;?i?????????StringBuilder?sb?=?new?StringBuilder();
        ????????String?s?=?sb.append(str1).append(i).append(str2).append(i).append(str3).append(i).append(str4).toString();
        ????}
        }

        第二組:

        多次 For 循環(huán)拼接一個(gè)字符串,循環(huán)結(jié)束后使用字符串,使用后由垃圾回收器回收。也是分別使用 String 和 StringBuilder 拼接

        /**
        ?*?多次循環(huán)拼接成一個(gè)字符串?用 String,這篇推薦看下:不能用 + 拼接字符串?
        ?*/
        public?static?void?useStringSpliceOneStr?(){
        ????String?str?=?"";
        ????for?(int?i?=?0;?i?????????str?+=?str1?+?str2?+?str3?+?str4?+?i;
        ????}
        }

        /**
        ?*?多次循環(huán)拼接成一個(gè)字符串?用?StringBuilder
        ?*/
        public?static?void?useStringBuilderSpliceOneStr(){
        ????StringBuilder?sb?=?new?StringBuilder();
        ????for?(int?i?=?0;?i?????????sb.append(str1).append(str2).append(str3).append(str4).append(i);
        ????}
        }

        為了保證測(cè)試質(zhì)量,在每個(gè)測(cè)試項(xiàng)目進(jìn)行前。線程休息 2s,之后空跑 5 次熱身。最后執(zhí)行 5 次求平均時(shí)間的方式計(jì)算時(shí)間

        public?static?int?executeSometime(int?kind,?int?num)?throws?InterruptedException?{
        ????Thread.sleep(2000);
        ????int?sum?=?0;
        ????for?(int?i?=?0;?i?????????long?begin?=?System.currentTimeMillis();

        ????????switch?(kind){
        ????????????case?1:
        ????????????????useString();
        ????????????????break;
        ????????????case?2:
        ????????????????useStringBuilder();
        ????????????????break;
        ????????????case?3:
        ????????????????useStringSpliceOneStr();
        ????????????????break;
        ????????????case?4:
        ????????????????useStringBuilderSpliceOneStr();
        ????????????????break;
        ????????????default:
        ????????????????return?0;
        ????????}

        ????????long?end?=?System.currentTimeMillis();

        ????????if(i?>?5){
        ????????????sum?+=?(end?-?begin);
        ????????}
        ????}
        ????return?sum?/?num;
        }

        主方法

        public?class?StringTest?{
        ????public?static?final?int?CYCLE_NUM_BIGGER?=?10_000_000;
        ????public?static?final?int?CYCLE_NUM_LOWER?=?10_000;
        ????public?static?final?String?str1?=?"張三";
        ????public?static?final?String?str2?=?"李四";
        ????public?static?final?String?str3?=?"王五";
        ????public?static?final?String?str4?=?"趙六";


        ????public?static?void?main(String[]?args)?throws?InterruptedException?{
        ????????int?time?=?0;
        ????????int?num?=?5;

        ????????time?=?executeSometime(1,?num);
        ????????System.out.println("String拼接?"+?CYCLE_NUM_BIGGER?+"?次,"?+?num?+?"次平均時(shí)間:"?+?time?+?"?ms");

        ????????time?=?executeSometime(2,?num);
        ????????System.out.println("StringBuilder拼接?"+?CYCLE_NUM_BIGGER?+"?次,"?+?num?+?"次平均時(shí)間:"?+?time?+?"?ms");

        ????????time?=?executeSometime(3,?num);
        ????????System.out.println("String拼接單個(gè)字符串?"+?CYCLE_NUM_LOWER?+"?次,"?+?num?+?"次平均時(shí)間:"?+?time?+?"?ms");

        ????????time?=?executeSometime(4,?num);
        ????????System.out.println("StringBuilder拼接單個(gè)字符串?"+?CYCLE_NUM_LOWER?+"?次,"?+?num?+?"次平均時(shí)間:"?+?time?+?"?ms");

        ????}
        }?

        測(cè)試結(jié)果

        測(cè)試結(jié)果如下

        結(jié)果分析

        第一組

        10_000_000 次循環(huán)拼接,在循環(huán)內(nèi)使用 String 和 StringBuilder 的效率是一樣的!為什么呢?看下這篇:不能用 + 拼接字符串??你就清楚了。關(guān)注Java技術(shù)棧公眾號(hào)回復(fù)Java獲取更多Java干貨教程。

        使用 javap -c StringTest.class 反編譯查看兩個(gè)方法編譯后的文件:

        可以發(fā)現(xiàn) String 方法拼接字符串編譯器優(yōu)化后使用的就是 StringBuilder、因此用例1 和用例2 的效率是一樣的。

        第二組

        第二組的結(jié)果就是大家喜聞樂(lè)見(jiàn)的了,由于 10_000_000 次循環(huán)String 拼接實(shí)在太慢所以我采用了 10_000 次拼接來(lái)分析。

        分析用例3:雖然編譯器會(huì)對(duì) String 拼接做優(yōu)化,但是它每次在循環(huán)內(nèi)創(chuàng)建 StringBuilder 對(duì)象,在循環(huán)內(nèi)銷(xiāo)毀。

        下次循環(huán)他有創(chuàng)建。相比較用例4在循環(huán)外創(chuàng)建,多了 n 次 new 對(duì)象、銷(xiāo)毀對(duì)象的操作、n - 1 次將 StringBuilder 轉(zhuǎn)換成 String 的操作 。效率低也是理所應(yīng)當(dāng)了。

        擴(kuò)展

        第一組的測(cè)試還有一種寫(xiě)法:

        /**
        ?*?循環(huán)內(nèi)?使用?StringBuilder?拼接字符串,一次循環(huán)后銷(xiāo)毀
        ?*/
        public?static?void?useStringBuilderOut(){
        ????StringBuilder?sb?=?new?StringBuilder();
        ????for?(int?i?=?0;?i?//????????????sb.setLength(0);
        ????????sb.delete(0,?sb.length());
        ????????String?s?=?sb.append(str1).append(i).append(str2).append(i).append(str3).append(i).append(str4).toString();
        ????}
        }

        循環(huán)外創(chuàng)建 StringBuilder 每次循環(huán)開(kāi)始的時(shí)候清空 StringBuilder 的內(nèi)容然后拼接。這種寫(xiě)法無(wú)論使用 sb.setLength(0); 還是 sb.delete(0, sb.length()); 效率都比直接在循環(huán)內(nèi)使用 String / StringBuilder 慢。

        奈何才疏學(xué)淺我一直想不明白為什么他慢。我猜測(cè)是 new 對(duì)象的速度比重置長(zhǎng)度慢,于是這樣測(cè)試了以下:

        public?static?void?createStringBuider()?{
        ????for?(int?i?=?0;?i?????????StringBuilder?sb?=?new?StringBuilder();
        ????}
        }

        public?static?void?cleanStringBuider()?{
        ????StringBuilder?sb?=?new?StringBuilder();
        ????for?(int?i?=?0;?i?????????sb.delete(0,?sb.length());
        ????}
        }

        但是結(jié)果是 cleanStringBuider 更快。

        結(jié)論

        • 編譯器會(huì)將 String 拼接優(yōu)化成使用 StringBuilder,但是還是有一些缺陷的。主要體現(xiàn)在循環(huán)內(nèi)使用字符串拼接,編譯器不會(huì)創(chuàng)建單個(gè) StringBuilder 以復(fù)用

        • 對(duì)于多次循環(huán)內(nèi)拼接一個(gè)字符串的需求:StringBuilder 很快,因?yàn)槠浔苊饬?n 次 new 對(duì)象、銷(xiāo)毀對(duì)象的操作,n - 1 次將 StringBuilder 轉(zhuǎn)換成 String 的操作

        • StringBuilder 拼接不適用于循環(huán)內(nèi)每次拼接即用的操作方式。因?yàn)榫幾g器優(yōu)化后的 String 拼接也是使用 StringBuilder 兩者的效率一樣。后者寫(xiě)起來(lái)還方便...

        版權(quán)申明:本文首發(fā)于博客園,作者:@后青春期的Keats
        鏈接:www.cnblogs.com/keatsCoder/p/13212289.html
        最近熱文:
        1、盤(pán)點(diǎn) 6 個(gè)被淘汰的 Java 技術(shù),曾經(jīng)風(fēng)光過(guò)!
        2、Spring Boot 太狠了,一次發(fā)布 3 個(gè)版本!
        3、Spring Boot Redis 實(shí)現(xiàn)分布式鎖,真香!
        4、Spring Boot 如何快速集成 Redis?
        5、Java 14 祭出神器,Lombok 被干掉了?
        6、Java 14 祭出增強(qiáng)版 switch,真香!!
        7、Spring Boot 2.3 優(yōu)雅關(guān)閉新姿勢(shì),真香!
        8、Spring Boot 干掉了 Maven 擁抱 Gradle!
        9、公司來(lái)了個(gè)新同事不會(huì)用 Lombok!
        10、Spring Cloud 2020 版本重大變革!
        掃碼關(guān)注Java技術(shù)棧公眾號(hào)閱讀更多干貨。

        點(diǎn)擊「閱讀原文」獲取面試題大全~

        瀏覽 28
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            xxxx18hd亚洲hd捆绑 | 大型操逼网站 | 国产中文字幕一区二区 | 他扒开我的内裤吻我下边 | 欧美狂猛XXXXX乱大交3 | 撩起老师旗袍挺进去玉足 | 91黄色大片| 国产精品无套久久久久 | 色噜噜狠狠躁夜夜躁人人爽免费 | 日韩无码视频网站 |