StringBuilder為什么非你不可
在String你還需要知道這些細(xì)節(jié)中提到過,由于String被設(shè)計成immutable,所以才有了StringBuilder和StringBuffer這2個類來幫助我們操作字符串,StringBuilder線程不安全,StringBuffer線程安全,在我們大多數(shù)日常使用場景,都是單線程操作字符串,所以StringBuidler用的會多一些,而且編譯器也會默認(rèn)幫我們將+號字符串拼接轉(zhuǎn)化為StringBuidler append,這篇文章我會跟大家分享我知道的StringBuilder使用的一些騷操作。
先拋出3個問題
- StringBuilder的底層實現(xiàn)?插入刪除的效率如何?
- StringBuilder的擴(kuò)容策略?
- StringBuilder為什么沒有clear方法?有沒有替代方法?
StringBuilder的底層實現(xiàn)?插入刪除的效率如何?
這個問題只要看下Jdk的源碼就能清楚

底層數(shù)據(jù)結(jié)構(gòu)很簡單,就是一個char[] value 和大小字段 count,構(gòu)造器生成的char[] 默認(rèn)capacity大小是16,如果很明確插入的字符串很長,應(yīng)該將capacity設(shè)置大一些,避免頻繁拷貝數(shù)組擴(kuò)容。
接下來,我們看下StringBuilder 插入刪除的實現(xiàn)


可以看到,由于是基于數(shù)組實現(xiàn)的,所以插入刪除的效率都不會太高,畢竟都要進(jìn)行數(shù)組的拷貝,但是也不必太過擔(dān)心,System.arrayCopy的速度還是很快的。
這里我想提一點,append和insert方法都能增長字符串,該如何選擇,看上面的源碼可以看到,insert不論字符串插入的位置是在中間還是最后,都會進(jìn)行數(shù)組拷貝,而append則會根據(jù)當(dāng)前數(shù)組的長度來判斷是否需要拷貝擴(kuò)容,所以如果需要在尾部增加字符串使用append,其他位置使用insert。
StringBuilder的擴(kuò)容策略?
我們看一下StringBuilder append方法

可以看到,在字符數(shù)組大小不足夠容納新的字符的時候,會進(jìn)行擴(kuò)容,而擴(kuò)容后的大小是原來數(shù)組的大小+新字符串的長度,所以這里的擴(kuò)容策略是非常保守的,只能夠容納這一次的append操作,所以如果我們要在循環(huán)內(nèi)頻繁進(jìn)行append操作,可以將StringBuilder初始大小capacity設(shè)置大一些,避免頻繁擴(kuò)容數(shù)組拷貝
StringBuilder為什么沒有clear方法?有沒有替代方法?
平常我們使用的Jdk集合類,如ArrayList,HashMap等都會有clear方法來清空數(shù)據(jù),但是StringBuilder沒有提供這個方法,那我們?nèi)绾吻蹇誗tringBuilder中的數(shù)據(jù)呢,難道非要循環(huán)去調(diào)用delete?當(dāng)然不用,StringBuilder另外給我們提供了setLength方法,參數(shù)傳0,就達(dá)到了清空數(shù)據(jù)的作用。

通過源碼可以看到,setLength方法,當(dāng)傳入的新length小于原來的count時,只是簡單的將count設(shè)為新length,并不會去動原來的字符數(shù)組value,相當(dāng)于count是一個指針,只是在移動指針,避免了數(shù)組拷貝,效率比較高。這個又引出了一個新問題,既然setLength不會去改變value數(shù)組,那value占用的內(nèi)存怎么釋放呢?
value占用的內(nèi)存怎么釋放
StringBuilder 提供了trimToSize方法

以上(安排的很明白),水平有限,各位大佬輕點噴??