Java 中的 String娘荡、StringBuffer干旁、StringBuilder 效率

Java 中的 String、StringBuffer炮沐、StringBuilder

  • 《阿里巴巴 Java 開發(fā)手冊》中有一條是關(guān)于字符串拼接的建議:
123
  • 上面說使用 + 拼接會造成資源浪費争群,就是消耗內(nèi)存,我們就簡單模擬一下大年。

開干

  • 使用 for 循環(huán)分別對String换薄、StringBuffer玉雾、StringBuilder進(jìn)行 10000 次字符串拼接,并統(tǒng)計耗時轻要。

使用 String 拼接:

static void StringTest() {
    String str = "";
    long begin = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        str += i;
    }
    long end = System.currentTimeMillis();
    long result = end- begin;
    System.out.println("String 拼接耗時:" + result);
}

使用 StringBuffer 拼接:

static void StringBufferTest() {
    StringBuffer str = new StringBuffer();
    long begin = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        str.append(i);
    }
    long end = System.currentTimeMillis();
    long result = end- begin;
    System.out.println("StringBuffer 拼接耗時:" + result);
}

使用 StringBilder 拼接:

static void StringBuilderTest() {
    StringBuilder str = new StringBuilder();
    long begin = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        str.append(i);
    }
    long end = System.currentTimeMillis();
    long result = end- begin;
    System.out.println("StringBuilder 拼接耗時:" + result);
}

結(jié)果

上面的代碼复旬,同一電腦執(zhí)行結(jié)果是(單位為:Millis):

String 拼接耗時:23051
StringBuffer 拼接耗時:4
StringBuilder 拼接耗時:3
  • 結(jié)果表明,三者的執(zhí)行效率是: StringBuilder > StringBuffer > String冲泥。其中 String 的耗時居然是 StringBuffer 和 StringBuilder 的幾千倍赢底。

接下來找下他們的效率快慢的原因。

分析

關(guān)于 String

String 是不可擴展的字符串變量

String 的工作方式

  • 以下舉個例子:
String str = "ABCD";
str += "加點東西";

我們都知道 String 是不可擴展的字符串變量(內(nèi)存地址不會變柏蘑,創(chuàng)建了之后,該常量就不會改變了)粹庞,當(dāng)編譯器執(zhí)行 String str = "ABCD"; 的時候咳焚,內(nèi)存的方法區(qū)中會分配一個空間給常量 "ABCD", 棧中的變量 str 指向常量 "ABCD" 的內(nèi)存地址,這時候完成 String str = "ABCD"; 這行代碼庞溜。

這時候如果我們對 str 進(jìn)行拼接操作革半,即執(zhí)行 str += "加點東西"; , 那么編譯器首先會在方法區(qū)的常量池尋找有沒有 "ABCD加點東西" 這個字符串常量(這時候肯定是沒有該常量)。那么編譯器會在常量池中重新開辟一塊空間給 "ABCD加點東西" (但是其實這個步驟流码,在底層實現(xiàn)的時候也是每次循環(huán)都會 StringBuilder對象又官,并調(diào)用其中的 append 方法進(jìn)行拼接, 這也印證了為什么會 String 比 StringBuilder 效率低),棧中的 str 變量指向 "ABCD加點東西" 的內(nèi)存地址漫试,完成一次拼接六敬。

  • 這樣做就十分費內(nèi)存,也就是浪費資源驾荣。

關(guān)于 StringBuffer 和 StringBuilder

StringBuffer 和 StringBuilder 都是可擴展的字符串類型外构。

StringBuffer 和 StringBuilder 工作方式

  • 舉個例子:
StringBuilder sb = new StringBuilder("ABCD");
sb.append("加點東西");
// 或者以下
StringBuffer sb = new StringBuffer("ABCD");
sb.append("加點東西");

StringBuffer 和 StringBuilder 的內(nèi)部數(shù)組 默認(rèn)長度 = 初始化字符串長度 + 16。所以當(dāng) new StringBuilder("ABCD"); 執(zhí)行完 new 之后播掷,實際上在 sb 中的 capacity() 的返回值是 20审编。 這時候會在堆區(qū)創(chuàng)建一個 StringBuffer 或者 StringBuilder 對象躁倒,同時會到方法去的產(chǎn)量池中尋找是否有 "ABCD" 這個常量驯绎,然后 StringBuffer 或者 StringBuilder 對象指向常量池的 "ABCD" 這個常量。

當(dāng)執(zhí)行 sb.append("加點東西"); 這行代碼的時候淑蔚,編譯器就會去常量池找是否有 "ABCD加點東西" 常量件炉,如果沒有那么就看 StringBuffer 或者 StringBuilder 對象 的長度能都裝載下 "加點東西" 該字符串(如果不夠那么就增加到當(dāng)前長度的 150%)勘究。此時的內(nèi)存地址是不變的。

  • 所以相對 String 的每次拼接都要在內(nèi)存中重新分配一塊內(nèi)存空間妻率,StringBuffer 或者 StringBuilder 的效率自然而言要給 String 的拼接速度要快乱顾。

StringBuffer 和 StringBuilder 區(qū)別

  • 既然說 StringBuffer 和 StringBuilder 效率差不多,那么為啥還要兩個宫静?其中有什么區(qū)別呢走净?

StringBufferStringBuilder 的實現(xiàn)方法前多了一個 synchronized券时,也就是同步鎖,這樣會使 StringBuffer 在并發(fā)編程中更加安全伏伯,可靠橘洞。StringBuilder 在日常開發(fā)中是最常見,也是效率最高的说搅。

小結(jié)

  • 拼接效率:
StringBuilder > StringBuffer > String 
  • 推薦使用 StringBuilder炸枣。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市弄唧,隨后出現(xiàn)的幾起案子适肠,更是在濱河造成了極大的恐慌,老刑警劉巖候引,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侯养,死亡現(xiàn)場離奇詭異,居然都是意外死亡澄干,警方通過查閱死者的電腦和手機逛揩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來麸俘,“玉大人辩稽,你說我怎么就攤上這事〈用模” “怎么了逞泄?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長静檬。 經(jīng)常有香客問我炭懊,道長,這世上最難降的妖魔是什么拂檩? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任侮腹,我火速辦了婚禮,結(jié)果婚禮上稻励,老公的妹妹穿的比我還像新娘父阻。我一直安慰自己,他們只是感情好望抽,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布加矛。 她就那樣靜靜地躺著,像睡著了一般煤篙。 火紅的嫁衣襯著肌膚如雪斟览。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天辑奈,我揣著相機與錄音苛茂,去河邊找鬼已烤。 笑死,一個胖子當(dāng)著我的面吹牛妓羊,可吹牛的內(nèi)容都是我干的胯究。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼躁绸,長吁一口氣:“原來是場噩夢啊……” “哼裕循!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起净刮,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剥哑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后淹父,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體星持,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年弹灭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揪垄。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡穷吮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饥努,到底是詐尸還是另有隱情捡鱼,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布酷愧,位于F島的核電站驾诈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏溶浴。R本人自食惡果不足惜乍迄,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望士败。 院中可真熱鬧闯两,春花似錦、人聲如沸谅将。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饥臂。三九已至逊躁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隅熙,已是汗流浹背稽煤。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工核芽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人念脯。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓狞洋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绿店。 傳聞我的和親對象是個殘疾皇子吉懊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354