2011-10-19 40 views
29

,當是StringBuilder的首選和什麼時候適合使用CONCAT。字符串連接 - 我們什麼時候應該使用+字符串的級聯時使用+,StringBuilder的和CONCAT

我聽說過的StringBuilder優選的循環中串聯。爲什麼這樣?

謝謝。

+0

第一件事是,每一次你使用一個普通的字符串,你分配一個對象(向GarbageCollector提供工作),而使用StringBuilder或StringBuffer可以讓您使用單個對象。 – BigMike

回答

20

我傾向於在代碼路徑,其中性能是一個問題使用StringBuilder。循環內的重複字符串連接通常是一個很好的選擇。

更喜歡StringBuilder的原因是,+concat都會在您每次調用它們時創建一個新對象(只要右側參數不爲空)。這可以快速添加到很多對象中,幾乎所有對象都是不必要的。

正如其他人所指出的那樣,當你使用相同的語句中+多次,編譯器通常可以優化這個給你。但是,根據我的經驗,當連接發生在單獨的語句中時,這個說法不適用。它肯定對循環沒有幫助。

說了這麼多,我覺得當務之急應當字跡清晰的代碼。 Java有一些很棒的性能分析工具(我使用YourKit),可以很容易地找出性能瓶頸,並優化其中的關鍵位。

P.S.我從來沒有需要使用concat

+0

我只有一次使用'concat()',那就是用方法引用''foo「:: concat'來替換'str - >」foo「+ str'。 – shmosel

40

現代Java編譯器通過的StringBuilder的append轉換您的+操作。我的意思是說,如果你做str = str1 + str2 + str3那麼編譯器會生成以下代碼:

StringBuilder sb = new StringBuilder(); 
str = sb.append(str1).append(str2).append(str3).toString(); 

可以使用DJ或Cavaj證實了這一點:) 所以現在選擇,而不是性能優勢的公司更多的事情來反編譯代碼使用+或StringBuilder :)

但是,考慮到編譯器不會爲你做這件事的情況(如果你使用任何私有Java SDK來做它然後它可能會發生),那麼當然StringBuilder是你的方式去作爲你最終避免大量不必要的String對象。

+8

是的,但是如果您在循環中使用'+',運行時將爲每次迭代創建一個新的'StringBuilder',從而導致嚴重的性能損失。 –

+1

您可以在開始循環之前創建STringBuilder。如果你每次都在循環中創建StringBuilder,那麼你將會丟失StringBuilder的previos數據。 – Saurabh

+0

@Sahil:編譯器或優化器可以解決這個問題。 –

5

如果所有連接的元素都是常量(例如:"these" + "are" + "constants"),那麼我更喜歡+,因爲編譯器會爲您內聯串聯。否則,使用StringBuilder是最有效的方法。

如果你在非常量中使用+,編譯器也會在內部使用StringBuilder,但是調試變得很糟糕,因爲所使用的代碼與源代碼不再相同。級聯2個或3字符串時只需保持代碼簡短易讀用途:

2

我的建議如下:

  • +
  • StringBuilder:在構建複雜的字符串輸出或性能問題時使用。
  • String.format:你沒有提到這在你的問題,但它是我的,因爲它使代碼生成字符串首選方法是最可讀/簡潔的在我看來,是日誌語句特別有用。
  • concat:我不認爲我有過這樣的理由。
1

如果您進行了大量操作,請使用StringBuilder通常一個循環是一個很好的指示。

這樣做的原因在於,使用正常級聯產生大量不能容易地被「擴展」(即,每個級聯操作產生一個複製,要求存儲器和CPU時間作出)中間String對象的。另一方面,StringBuilder只需要在某些情況下複製數據(在中間插入某些內容,或者因爲結果變大而不得不調整大小),因此可以節省這些複製操作。

使用concat()比使用+沒有真正的好處(這可能是非常輕微快單個+,但一旦你做a.concat(b).concat(c)它實際上將比a + b + c較慢)。

1

從編譯器中的服務表現增益適用於串聯常數。 其餘的用途實際上比使用StringBuilder直接更慢。

使用「+」例如爲Exception創建一條消息,因爲它不會經常發生,應用程序si現在已經以某種方式被破壞了。 避免在循環中使用「+」。

爲了創建有意義的信息或其它參數化(Xpath的表達式例如)使用的String.format - 它是要好得多可讀。

1

使用單個語句和StringBuilder的多個語句/循環+。

11

Java/J2EE Job Interview Companion

String

String是不可變的:你不能修改String對象,但可以通過創建一個新的實例來替換它。創建一個新實例相當昂貴。

//Inefficient version using immutable String 
String output = "Some text"; 
int count = 100; 
for (int i = 0; i < count; i++) { 
    output += i; 
} 
return output; 

上面的代碼將建立新的99名String對象,其中98將立即扔掉。創建新對象效率不高。

StringBuffer/StringBuilder

StringBuffer是可變的:使用StringBufferStringBuilder當你要修改的內容。在Java 5中添加了StringBuilder,它在所有方面均與StringBuffer相同,不同之處在於它不同步,這使得其以不是線程安全的代價略快。

//More efficient version using mutable StringBuffer 
StringBuffer output = new StringBuffer(110); 
output.append("Some text"); 
for (int i = 0; i < count; i++) { 
    output.append(i); 
} 
return output.toString(); 

上面的代碼僅創建兩個新的對象,則StringBuffer並返回最終StringStringBuffer根據需要進行擴展,但成本高昂,因此如圖所示,從一開始就以最佳尺寸初始化StringBuffer會更好。

+0

加書1鏈接。 (無法將「+」標記添加爲「評論不能包含該內容」:)) –

相關問題