看板 java 關於我們 聯絡資訊
本來想說 Java Code Geeks 的文章應該沒啥問題 所以翻完就算了,沒有仔細追究 BUT! M Jwo 在 blog 上留了一個 comment 坦白說我看不是很懂,全文如下 本文大錯,僅有在 compiler 可以最佳化的有限場景才是, 通常是宣告的地方,不然放到method/loop裡面就知道了, 因為只有在 method/loop 才會對效能造成大影響, 少數幾個 String 根本不再效能需要調教的地方。 其實根本不用那麼麻煩,de-compiler 看一眼就知道 都是改用 StringBuffer/StringBuilder 了。 然後我才真的去翻了原作者提供的 javap 的結果 https://github.com/skuro/stringbuilder/blob/master/java7/CatPlus.class.txt 如果你跟我一樣沒辦法直接看懂 javap 那麼對應原始碼可能比較好懂 public class CatPlus extends ACat { @Override protected String cat(String base, String append){ String result = "const1" + base; result = result + "const2"; return result + append; } } 也就是說,根本不是他說的那麼一回事情 在 Oracle JDK 7 之下,其實會用 append() 來代替 + 號 原作者 javap 的結果也是如此 要說效能慢的話,應該是因為他重複 assign 回 result 有 code 為證 我寫了一個單純的 class,在 JDK 6 下測試 public class CatPlus { public String foo (String a, String b) { return "const1" + a + "const2" + b; } } javap 之後會得到 public class CatPlus extends java.lang.Object{ public CatPlus(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public java.lang.String foo(java.lang.String, java.lang.String); Code: 0: new #2; //class java/lang/StringBuilder 3: dup 4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 7: ldc #4; //String const1 9: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: aload_1 13: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: ldc #6; //String const2 18: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 21: aload_2 22: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 25: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 28: areturn } 所以,至少在 Oracle JDK 6 以後 字串用 + 號作連接跟用 StringBuilder 沒啥差別 ======== 只能說... 嗯... 愚人節快樂這樣? [核爆] -- 錢鍾書: 說出來的話 http://www.psmonkey.org 比不上不說出來的話 Java 版 cookcomic 版 只影射著說不出來的話 and more...... -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.25.15.134
AI3767:很久以前我也做過+和sb測試,有發現速度一樣, 但,sb方便用於 04/01 23:12
AI3767:在不同程式片段做接合. +比較適合所需字串一次性生成時 04/01 23:15
cyclone350:我有點不懂,這在說用+號會被編譯成append,那位啥最後 04/01 23:21
cyclone350:的結論,會是需要明確指定用 StringBuilder 來增進效能 04/01 23:24
cha122977:是不是使用場合有差?一次性字串用+沒什麼差別, 04/01 23:26
cyclone350:版主最後一句說沒啥差別,原文說多50% !? 04/01 23:28
cha122977:但是摻雜判斷式而產生的字串 用StringBuilder比較好? 04/01 23:28
cha122977:(是說推文間隔可不可以短一點 討論起來好痛苦阿囧) 04/01 23:29
本來就不應該用推文的方式來討論 這樣看的人會很痛苦 另外,Java 版從來沒有限制文章字數 or 行數 只在意是否言之有物 請見諒
cyclone350:多50% 是愚人節的玩笑嗎 ?? 04/01 23:31
cha122977:話說曾在版上看過一篇跑很慢的 改用StringBuilder就解了 04/01 23:32
cha122977:找到了 是這個~ #1Fc1oO9j 04/01 23:34
其實原文也不是那麼悽慘到完全無用 或著說,他給的 CatPlus 的 test case 其實就是要模擬 #1Fc1oO9j 的狀態,也就是 while(FooCondition) { str += str; } 在這種情況下,雖然 + 的動作還是會改成用 append() 但是會重複宣告 StringBuilder 這才是真正造成效能瓶頸的地方 + 號還是會變成 append() 的,這點可以肯定 只能說原 po(包含我)不夠用功,不夠龜毛 外加沾染了國內記者的習性,喜歡標題殺人,如此而已 (謎之聲:還而已咧 [毆殺]) 是說,要不是看了這篇 我還真的不知道原本的 + 號惡魔其實已經被處理掉了 XD ※ 編輯: PsMonkey 來自: 114.25.15.134 (04/01 23:46)
AI3767:那篇在迴圈內+=, 不是一次性加起來, 確實很高可能造成變慢 04/01 23:46
cha122977:可以請教為何 str+=str; 會重複宣告嗎?不太明白 04/01 23:56
coolcomm:會在每次迴圈產生新的instance 04/02 01:05