關于StringBuilder內部實現(xiàn)詳解

在平常的開發(fā)都說對于字符串的拼湊時,要盡量使用StringBuilder來操作零渐,特別是對于長字符串的拼湊窒舟。但是卻很少知道為什么要這樣做,在直接使用字符串進行拼湊時诵盼,編譯器到底是怎么將"+"完成字符串拼湊的惠豺,它的弊端又是上面,而使用StringBuilder內部又是如何優(yōu)化的呢风宁?

現(xiàn)在我們來扒一扒其中的緣由洁墙,知其然而知其所以然。

首先我們來看下面這個例子:

public class StringDemo2{
        public static void main(String[] args) {
            String str = "";
            for (int i = 0; i < 10; i++) {
                str+=i;
            }
        System.out.println(str);
        }
  }

在拼湊str3字符串時戒财,編譯器在編譯該.java文件時热监,幫我們添加了上面東西呢?我們通過javap指令來查看編譯后.class指令文件

在編譯期饮寞,編譯器會幫我們生成一個StringBuilder對象狼纬,同時將使用+拼湊字符的過程,轉換成調用StringBuilder的append( )方法進行拼湊骂际。

這是有人會說內部的實現(xiàn)跟我們直接用StringBuilder對象進行拼湊是一樣的啊疗琉,都是使用StringBuilder,都是使用append方法。其實細看還是有很大差別的歉铝,編譯器并不會很智能盈简,它只能將有+號操作的做出轉換成StringBilder對象的append方法,作完這個+操作后,又調用了StringBuilder的toString()方法太示,該方法的內部是直接new String(.. )對象進行返回字符串的柠贤。接下來又繼續(xù)重復該動作,進行拼湊字符串

這樣不斷的new StringBuilder() --> append()--->toString(), new StringBuilder() --> append()--->toString() ...的操作类缤,將會創(chuàng)建大量的對象臼勉,而真正需要使用的字符串只是最后拼湊好的字符串,這樣則造成的大量內存的浪費餐弱。

對于少量字符串的拼湊還算能接觸宴霸,但對于大量且長文本的字符串則對于系統(tǒng)的開銷就很大了。像這種不必要的內存浪費膏蚓,我們當然要杜絕發(fā)生了瓢谢。

而直接使用StringBuilder,拼湊字符串驮瞧,其內部又是如何做的呢氓扛?

我們先將上面的例子改成StringBuilder來實現(xiàn)

public class StringDemo2{
    public static void main(String[] args) {
          String str = "";
          StringBuilder sb = new StringBuilder(str);
          for (int i = 0; i < 10; i++) {
                  sb.append(i);
          }
          System.out.println(sb.toString());
    }
}

同樣適用javap查看文件指令:

從該字節(jié)碼指令可以看出,在拼湊字符串時论笔,只生成了一個StringBuilder對象用于拼湊采郎,拼湊完后只生成了一個Sting對象千所,這樣大大節(jié)省了內存開銷,提高了效率蒜埋。

由于String字符串是不可變的真慢,每次的該包都會生成新的字符串,而StringBuilder內部是如何實現(xiàn)在內部append( )方法時提供復用性的呢理茎?

我們來看到StringBuilder源碼,首先StringBuilder繼承至一個AbstractStringBuilder的抽象類管嬉。

在該AbstractStringBuilder抽象類中皂林,在該類中有兩個重要的成員變量:

其中char[ ] value就是用來實現(xiàn)字符串緩沖池的核心,count數(shù)是用來記錄StringBuilder內部中真實的字符長度的蚯撩。細心的小伙伴可能要問了础倍,干嘛不直接使用char[] 數(shù)組的長度表示字符的長度呢?繼續(xù)往下看就知道了胎挎。

在初始化一個StringBuilder對象是沟启,如果使用個都是默認構造器進行初始化,在StringBuilder的默認構造器會調用父類抽象類的構造器犹菇,并傳入默認16的數(shù)值德迹,該數(shù)值用于初始化容緩沖池的大小,也就是初始化char[ ] 數(shù)組的長度揭芍,所有我們不能直接使用該長度來表示實際字符長度的胳搞。

調用append(String str)方法時,會調用其父類的append( )方法称杨,所有要查看append( )方法的內部實現(xiàn)肌毅,還是得去AbstractStringBuilder類中

進入AbstractStringBuilder 類的append方法

我們發(fā)現(xiàn),其內部的實現(xiàn)還是比較簡單的姑原⌒總的來說內部對append字符串的操作,在建立在char[ ]數(shù)組上的锭汛,當有新的字符串append進來時笨奠,會將該字符串轉會成對應的char[ ]字符數(shù)組 ,然后調用System.copyArray( ... )方法將其拷貝至StringBuilder內部char[ ] value數(shù)組中唤殴。這樣在拼湊字符串時艰躺,就不會像直接拼湊字符串那樣不斷創(chuàng)建新的String對象了。

在方法中還有一個內部字符容器擴容操作眨八,ensureCapacityInternal(count + len);順便我們來看出下該方法的操作腺兴,

minimumCapacity參數(shù)就是那個 count(原有的字符數(shù)) + len(新加入的字符數(shù))得到的值,如果該值大于了char[] valueStringBuilder內部的緩沖數(shù)組的長度廉侧,則說明原有的容器已經不夠裝了页响,需要對其進行擴容操作篓足。

將value原有的值都拷貝至一個新的char[ ] 數(shù)組中,該數(shù)組的長度是原來的2倍+2闰蚕。從這也可以看出栈拖,在使用StringBuilder拼湊廠字符串時,應該預估一個StringBuilder內部char[ ]容器的初始化長短值没陡,這樣就可以盡量的避免頻繁擴容帶來的性能損耗涩哟。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盼玄,隨后出現(xiàn)的幾起案子贴彼,更是在濱河造成了極大的恐慌,老刑警劉巖埃儿,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件器仗,死亡現(xiàn)場離奇詭異,居然都是意外死亡童番,警方通過查閱死者的電腦和手機精钮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剃斧,“玉大人轨香,你說我怎么就攤上這事∮锥” “怎么了弹沽?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長筋粗。 經常有香客問我策橘,道長,這世上最難降的妖魔是什么娜亿? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任丽已,我火速辦了婚禮,結果婚禮上买决,老公的妹妹穿的比我還像新娘沛婴。我一直安慰自己,他們只是感情好督赤,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布嘁灯。 她就那樣靜靜地躺著,像睡著了一般躲舌。 火紅的嫁衣襯著肌膚如雪丑婿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音羹奉,去河邊找鬼秒旋。 笑死,一個胖子當著我的面吹牛诀拭,可吹牛的內容都是我干的迁筛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼耕挨,長吁一口氣:“原來是場噩夢啊……” “哼细卧!你這毒婦竟也來了?” 一聲冷哼從身側響起筒占,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤贪庙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赋铝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡沽瘦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年革骨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片析恋。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡良哲,死狀恐怖,靈堂內的尸體忽然破棺而出助隧,到底是詐尸還是另有隱情筑凫,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布并村,位于F島的核電站巍实,受9級特大地震影響,放射性物質發(fā)生泄漏哩牍。R本人自食惡果不足惜棚潦,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膝昆。 院中可真熱鬧丸边,春花似錦、人聲如沸荚孵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽收叶。三九已至骄呼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谒麦。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工俄讹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绕德。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓患膛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親耻蛇。 傳聞我的和親對象是個殘疾皇子踪蹬,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容