(點選上方公眾號,可快速關註)
ImportNew – ImportNew讀者
通常我們需要把一些其它型別的值轉換為String,這些型別可能就包括基本型別。如果你有2個甚至更多的基本型別變數位於字串連線的開頭處,那麼你需要顯示地把他們轉換為String(否則 System.out.println(1+ ‘a’) 將列印98而不 是’la’).當然.你也可以使用String.valueOf方法(或者其他包裝類的方法)
把一個字面量為空的字串與一個基本型別的變數串連起來(在我們的示例中,””+1)是最簡單的方式,這個運算式的值就是一個字串,你可以很安全地把任何基本型別值連線在後面—-編譯器會很小心隱式地把他們轉換成String。
不幸的是,這是能想象的最糟糕的方式,為了理解為什麼是這樣,我們需要檢視下String連線操作在java中是被怎樣運作的。 假如有一個String值(字面值、變數或方法的傳回值) 後面跟隨“+”這個運運算元,再後面跟個其他任何運算式
String_exp + any_exp
java 編譯器將會翻譯成:
new StringBuilder().append(String_exp).append(any_exp).toString();
StringBuilder(String) 建構式分配一個包含16個字元的緩衝,所以追加最多16個字元的StringBuilder不需要重新分配緩衝,但追加超過16個字元的將需要擴充套件緩衝。最後,StringBuilder.toString()方法中將會利用StringBuilder的緩衝複製一個新的String物件傳回。
意味著一個單獨的基本型別值轉換為String的最壞一種情況是:你需要這樣分配:一個StringBuilder,一個長度為16的char陣列char[16],一個String和一個適合大小的char陣列,用String.valueOf方法至少可以避免建立一個 StringBuilder。
有時你實際完全不需要把基本型別轉換為String,例如:你解析一個被逗號符分割的String,最初的版本你可能會這樣寫
final int nextComma = str.indexOf(“‘”);
甚至這樣
final int nextComma = str.indexOf(‘\”);#註:反斜槓後面是兩個單引號
之後程式可能需要擴充套件至支援任何分隔符,當然支援任何分隔符意味著你需要一個Stirng物件的分隔符並且使用String.indexof(String)方法.我們建議把一個預設的分隔符儲存在m_separator 這變數中,程式碼看起來像這個:
private static List
split( final String str ) {
final List
res = new ArrayList ( 10 ); int pos, prev = 0;
while ( ( pos = str.indexOf( m_separator, prev ) ) != -1 )
{
res.add( str.substring( prev, pos ) );
prev = pos + m_separator.length(); // start from next char after separator
}
res.add( str.substring( prev ) );
return res;
}
但是後來你發現使用的分隔符從來就沒有超過一個字元,在初始化時,你會定義一個char型別m_separtor來替換String型別的m_separtor並且適當的改變它的setter方法。但你又不想大量的改動解析方法(為什麼我們如果改變這工作的程式碼呢?):
private static List
split2( final String str ) {
final List
res = new ArrayList ( 10 ); int pos, prev = 0;
while ( ( pos = str.indexOf(“” + m_separatorChar, prev ) ) != -1 )
{
res.add( str.substring( prev, pos ) );
prev = pos + 1; // start from next char after separator
}
res.add( str.substring( prev ) );
return res;
}
如你所看到的,indexOf方法被更改了。但是它還是建立了一個字串並且可用,當然這樣並不對,因為String API中本來就有一個多載的indexOf方法,它可以接受char型別的引數,我們改動下:
private static List
split3( final String str ) {
final List
res = new ArrayList ( 10 ); int pos, prev = 0;
while ( ( pos = str.indexOf( m_separatorChar, prev ) ) != -1 )
{
res.add( str.substring( prev, pos ) );
prev = pos + 1; // start from next char after separator
}
res.add( str.substring( prev ) );
return res;
}
測試如下, “abc,def,ghi,jkl,mno,pqr,stu,vwx,yz” 這個字串用這3種方法分別簡析10次,下麵是java 6_41 和 7_15的執行時間,java7的執行時間增加是因為String.subString方法變複雜 了,你可以閱讀這裡。
http://java-performance.info/changes-to-string-java-1-7-0_06/
如你所看到的,這樣簡單的重構就使splitting這個方法執行的時間得到了一個客觀的變化。
split | split2 | split3 | |
Java 6 | 4.65 sec | 10.34 sec | 3.8 sec |
Java 7 | 6.72 sec | 8.29 sec | 4.37 sec |
看完本文有收穫?請轉發分享給更多人
關註「ImportNew」,提升Java技能