學習Java的同學注意了!!!
學習進程中遇到甚么問題或想獲得學習資源的話,歡迎加入Java學習交換群,群號碼:183993990 我們1起學Java!
這兩天在淘測試的文章里看到1篇關于java string的文章,談到了StringBuilder和StringBuffer的使用效力的問題,然后發現自己疏忽了capacity這個概念。比如說下面的1段代碼:
1 StringBuffer sf = new StringBuffer(""); 2 sf.append("leeon"); 3 System.out.println("length: "+sf.length()); 4 System.out.println("capacity: "+sf.capacity());
這個打印的結果就是
length:5
capacity:16
length我們可以理解,那末capacity是甚么呢?
JDK源碼中給出的解釋就是用來存儲新插入的字符空間的容量,可見1個默許的容量就是16了,固然如果我們像下面這樣的去重寫上面的代碼,就會得到不1樣的結果。
1 StringBuffer sf = new StringBuffer("leeon"); 2 System.out.println("length: "+sf.length()); 3 System.out.println("capacity: "+sf.capacity());
這次的結果就是
length:5
capacity:21
緣由就是我們在構造sf的時候本身的value已是5了,再加上了新準備插入的初始化容量,也就是5+16.具體實現的細節是:
----------------------------------------------------------------------------------------------------------
以上是背景知識,下面開始討論如何從capacity這個特性動身來優化性能。再仔細瀏覽jdk源碼中append方法的實現的時候會發現,每次調用append都要進行容量的檢查,由于要確保StringBuffer足夠的大才能裝得下新添加的字符串。無妨再1起看下代碼:
當調用append的時候,首先會通過ensureCapacityInternal檢查所需的容量,如果容量不足再調用expandCapacity進行擴容,可以看見擴容的方式是將現在的字符串大小增加1倍然后再加上2.如果容量依然不足,則直接擴大到所需的大小。我們發現擴大容量就是1個耗時的操作,雖然處理大量字符串的時候采取StringBuffer會比用String更加的提升性能,但是卻依然存在可優化的耗時部份。
其實StringBuffer和StringBuilder在初始化的時候是可以指定capacity的,如果有1個大概的預估,初始化1個比較適合的capacity,減少擴大容量的操作,效力就會有更大的提高。比以下面的測試代碼,我們對一樣的字符串操作5百萬次,統計1下結果。
1 StringBuilder sb = new StringBuilder(10*5000000); 2 StringBuffer sf = new StringBuffer(10*5000000); 3 4 5 long start = System.currentTimeMillis(); 6 for(int i = 0; i < 5000000; i++) 7 { 8 sb.append("1234567890"); 9 } 10 long end = System.currentTimeMillis(); 11 System.out.println("the StringBuilder run time is "+(end -start)+" ms"); 12 13 start = System.currentTimeMillis(); 14 for(int i = 0; i < 5000000; i++) 15 { 16 sf.append("1234567890"); 17 } 18 end = System.currentTimeMillis(); 19 System.out.println("the StringBuffer run time is "+(end -start)+" ms");
上面的結果我沒有求平均值,測試也只是在單線程下進行的,但是數據波動不大,大致可以看出1些變化,我們發現當恰當的初始化了StringBuffer后,他的性能已和未初始化的StringBuilder相當乃至超過了,這樣我們就可以夠在保持和原來StringBuilder相當效力的基礎上有更好的安全性了。
可以看到采取了初始化的容量,我們取得的性能提升要高于從SF切換到SB。
淘測試總結的結論中有1個我很喜歡,援用1下
“ 用好現有的類比引入新的類更重要。很多程序員在使用 StringBuffer 時是不指定其容量的(最少我見到的情況是這樣),如果這樣的習慣帶入 StringBuilder 的使用中,你將只能取得 10 %左右的性能提升(不要忘了,你可要冒多線程的風險噢);但如果你使用指定容量的 StringBuffer ,你將馬上取得 45% 左右的性能提升,乃至比不使用指定容量的 StirngBuilder 都快 30% 左右。”
這個問題其實后續還值得討論,現在我們看到都是單線程的情況,那末多線程情況下,StringBuffer是否是可以優化的更多了?
忽然發現,自己疏忽了很多java的特性,學在當下。
學習Java的同學注意了!!!
學習進程中遇到甚么問題或想獲得學習資源的話,歡迎加入Java學習交換群,群號碼:183993990 我們1起學Java!
上一篇 json相關知識介紹
下一篇 小程序發布,你很方?