在String字符串拼接性能優(yōu)化?博客中我已經(jīng)介紹過了String "+" 拼接背后的StringBuilder實(shí)現(xiàn)洲胖。也聊到了StringJoiner、Joiner等類庫都是通過StringBuilder實(shí)現(xiàn)的拼接铃芦。
那么今天我們來聊一聊StringBuilder還有什么點(diǎn)比較好玩。
StringBuilder的使用上吹缔,應(yīng)該來說性能問題取決于擴(kuò)容操作是否頻繁咳蔚,還有char數(shù)組是否浪費(fèi)豪嚎,所以一般來說大家都聽過要預(yù)估一個(gè)StringBuilder的容量去構(gòu)造。那除此之外谈火,StringBuilder還有哪些空間可以讓我們搞一些優(yōu)化呢侈询?
在介紹優(yōu)化方式之前,需要一點(diǎn)基礎(chǔ)知識(shí)糯耍,我們看一段代碼
如上扔字,在StringBuilder對(duì)象重新設(shè)置length屬性之后,之前append的值沒有了温技。
然后我charAt發(fā)現(xiàn)char[]第一位變成了4革为,且不允許訪問第二位。
然后我們來看一下幾個(gè)方法的源碼
如上舵鳞,我們可以知道StringBuilder底層是一個(gè)char數(shù)組震檩,然后count代表的是append char字節(jié)的次數(shù),注意這里不是append的次數(shù)蜓堕,而是string拆成了char之后的length恳蹲。
然后toString就是操作一個(gè)new String(char[],0,count),跟JSON toJSONString那塊源碼一樣俩滥。
那么setLength其實(shí)就是重新賦值了count值嘉蕾,然后append操作又是從數(shù)組0位操作的。
所以在setLength為0之后霜旧,再append值抽诉,char[]就會(huì)從0位開始替換原來的值浪慌,可以debug驗(yàn)證一下。
如上圖,append("1","2","3")之后setLength為0宣蔚,之后append("4"),就會(huì)變成4失尖,2较剃,3組成的char[]。
最后輸出toString自然只會(huì)偏移count值的char出來个绍,那么就只會(huì)輸出4勒葱,而char[]復(fù)用了。
說到這里巴柿,是不是已經(jīng)有靈感了凛虽?
沒錯(cuò),我們對(duì)StringBuilder優(yōu)化的思路就在于復(fù)用char[]广恢。
那么第一版我們能想到的方案就是一個(gè)靜態(tài)單例工具類做法凯旋,如下:
這樣我就可以不用創(chuàng)建多個(gè)StringBuilder,只需要reset就能復(fù)用char[]且忽略之前append的值,這會(huì)讓我們節(jié)省char[]創(chuàng)建和擴(kuò)容的時(shí)間&空間成本至非。
這個(gè)版本基本上夠用了钠署,但是線程不安全,那么線程安全版本的如下:
這個(gè)版本最初的實(shí)現(xiàn)在哪里呢荒椭?BigDecimal源碼谐鼎、Netty源碼
所以沒事看看jdk源碼還是很重要的~