Tips
書中的源代碼地址:https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些代碼裏方法是基於Java 9 API中的,因此JDK 最好下載 JDK 9以上的版本。java
字符串鏈接操做符(+)是將幾個字符串組合成一個字符串的便捷的方法。對於生成單行輸出或構造一個小的、固定大小的對象的字符串表示形式,它是能夠的,可是它不能伸縮。重複使用字符串鏈接運算符來鏈接n個字符串須要n的平方級的時間。這是因爲字符串是不可變的這一事實致使的結果(條目 17)。當鏈接兩個字符串時,須要複製這兩個字符串的內容。git
例如,考慮這個方法,它經過爲每一個項目重複鏈接一行來構造帳單語句的字符串表示:github
// Inappropriate use of string concatenation - Performs poorly! public String statement() { String result = ""; for (int i = 0; i < numItems(); i++) result += lineForItem(i); // String concatenation return result; }
若是項的數量很大,則該方法的性能很是糟糕。爲了達到可接受的性能,使用StringBuilder
代替String來存儲正在構建的語句:數組
public String statement() { StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH); for (int i = 0; i < numItems(); i++) b.append(lineForItem(i)); return b.toString(); }
自Java 6以來,爲了使字符串鏈接更快,已經作了大量工做,可是這兩個方法在性能上的差別仍然很大:若是numItems返回100個元素,每一個lineForItem返回一個固定長度爲80個字符串,那麼在個人機器上運行,第二個方法的速度是第一個方法的6.5倍。因爲第一種方法在項目數量上是平方級增加的,而第二種方法是線性的,因此隨着項目數量的增長,性能差別會變得愈來愈大。注意,第二個方法預先分配了一個足夠大的StringBuilder來保存整個結果,從而消除了自動增加的須要。即便使用默認大小的StringBuilder,它仍然比第一個方法快5.5倍。app
道理很簡單:除非性能可有可無,不然不要使用字符串鏈接操做符組合多個字符串。而是使用StringBuilder的append方法。或者,使用字符數組,或者一次處理一個字符串,而不是把它們組合起來。性能