java開(kāi)發(fā)兩年拨齐,你知道StringBuffer的擴(kuò)容原理嗎?來(lái)看看阿里大牛是怎么講的吧

前言

在Java中鳞陨,String是一個(gè)常量,一旦創(chuàng)建其值后不能更改但可以共享瞻惋。

如果我們把多個(gè)字符串進(jìn)行連接(拼接)操作厦滤,就會(huì)開(kāi)辟很多空間,從而造成了大量?jī)?nèi)存空間的浪費(fèi)歼狼。

為了解決這個(gè)問(wèn)題掏导,我們需要用到StringBuffer類(lèi)和StringBuilder類(lèi)。

這兩個(gè)類(lèi)可牛逼了羽峰,它們都是可變長(zhǎng)度的字符串類(lèi)碘菜,在字符串的拼接處理上大大提高了效率。

一限寞、StringBuffer與StringBuilder的區(qū)別

共同點(diǎn):底層數(shù)據(jù)結(jié)構(gòu)都是char類(lèi)型的數(shù)組,都是可變的字符串仰坦。

不同點(diǎn):StringBuffer線程同步的安全性高履植,但多線程操作時(shí)效率低。StringBuilder線程不同步悄晃,進(jìn)行多線程操作時(shí)玫霎,安全性低凿滤,但效率高。

因?yàn)檫@兩個(gè)類(lèi)的用法都類(lèi)似庶近,所以我就以StringBuffer類(lèi)為例來(lái)講解翁脆。

二、StringBuffer類(lèi)的定義

StringBuffer類(lèi)的部分源碼:

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{

從源碼中可以看出鼻种,StringBuffer是一個(gè)用final修飾的最終類(lèi)反番,繼承了父類(lèi)AbstractStringBuilder類(lèi),實(shí)現(xiàn)了Serializable接口和CharSequence接口叉钥,說(shuō)明具備了兩種能力罢缸。

三、四個(gè)構(gòu)造方法

public StringBuffer() {
        super(16);
    }
public StringBuffer(int capacity) {
        super(capacity);
    }
public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

重點(diǎn)講下這兩個(gè)構(gòu)造方法:

構(gòu)造方法:StringBuffer()
方法描述:構(gòu)造一個(gè)沒(méi)有字符的字符串緩沖區(qū)投队,初始容量為16枫疆。

構(gòu)造方法:StringBuffer(String str)
方法描述:構(gòu)造一個(gè)初始化為指定字符串內(nèi)容的字符串緩沖區(qū),初始容量為str.length() + 16敷鸦。

實(shí)例:

package cn.tkr.demo;

public class MyStringBuffer {
    public static void main(String[] args) {
        
        StringBuffer sb1 = new StringBuffer();
        System.out.println("sb1字符緩沖區(qū)的容量:" + sb1.capacity()); //獲取當(dāng)前StringBuffer的容量

        StringBuffer sb2 = new StringBuffer("LoveJava");
        System.out.println("sb2字符緩沖區(qū)的容量:" + sb2.capacity()); //獲取當(dāng)前StringBuffer的容量
    }
}

運(yùn)行結(jié)果:

sb1字符緩沖區(qū)的容量:16
sb2字符緩沖區(qū)的容量:24

實(shí)例分析:調(diào)用無(wú)參數(shù)構(gòu)造函數(shù)息楔,sb1字符緩沖區(qū)的初始容量為16,調(diào)用有參數(shù)構(gòu)造函數(shù)扒披,初始容量為字符串的長(zhǎng)度(8) + 16值依,所以初始容量為24。

四谎碍、StringBuffer的常用方法

注: append(...)中的...代表各種類(lèi)型的參數(shù)鳞滨,如append(int i)、append(char c)蟆淀、append(String str)等

五拯啦、StringBuffer的擴(kuò)容原理

擴(kuò)容原理:

StringBuffer的底層數(shù)組結(jié)構(gòu)用的是char類(lèi)型的數(shù)組。

所以熔任,當(dāng)我們使用StringBuffer對(duì)象的append(...)方法追加數(shù)據(jù)時(shí)褒链,如果char類(lèi)型數(shù)組的長(zhǎng)度無(wú)法容納我們追加的數(shù)據(jù),StringBuffer就會(huì)進(jìn)行擴(kuò)容疑苔。

擴(kuò)容時(shí)會(huì)用到Arrays類(lèi)中的copyOf(...)方法甫匹,每次擴(kuò)容的容量大小是原來(lái)的容量的2倍加2。

注: copyOf(...)中的...代表各種類(lèi)型的參數(shù)惦费,如
copyOf(int[] original, int newLength)兵迅、copyOf(char[] original, int newLength)等

實(shí)例源碼分析:

假設(shè)我現(xiàn)在調(diào)用了append(String str)方法,追加了一個(gè)字符串(char類(lèi)型數(shù)組的長(zhǎng)度無(wú)法容納的字符串)薪贫。

append(String str)方法源碼:

public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

方法中通過(guò)super.append(str)調(diào)用了父類(lèi)的append(String str)方法恍箭。

父類(lèi)的append(String str)方法源碼:

public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

重點(diǎn)來(lái)了,這里的ensureCapacityInternal(count + len)就是一個(gè)擴(kuò)容相關(guān)的方法瞧省,變量count是一個(gè)全局變量扯夭,并沒(méi)有實(shí)際的值鳍贾,變量len是我們追加進(jìn)來(lái)的字符串的長(zhǎng)度。

也就是說(shuō)交洗,我們追加進(jìn)來(lái)的字符串的長(zhǎng)度會(huì)傳遞給ensureCapacityInternal(int minimumCapacity)方法骑科。

再來(lái)看看ensureCapacityInternal(int minimumCapacity)方法的源碼:

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

其中,minimumCapacity指我們追加進(jìn)來(lái)的字符串的長(zhǎng)度构拳,value是一個(gè)全局的char類(lèi)型的數(shù)組名咆爽。

也就說(shuō),value.length指數(shù)組的長(zhǎng)度隐圾,那如果(minimumCapacity - value.length > 0)這個(gè)條件成立伍掀,也就意味著,char類(lèi)型數(shù)組的長(zhǎng)度無(wú)法容納我們追加的字符串的長(zhǎng)度暇藏。

這時(shí)蜜笤,就需要使用Arrays類(lèi)中的copyOf(char[] original, int newLength)方法進(jìn)行擴(kuò)容。

方法:

copyOf(char[] original, int newLength)

描述:復(fù)制指定的數(shù)組盐碱,截?cái)嗷蚴褂孟鄳?yīng)的默認(rèn)值進(jìn)行填充

該方法的第一個(gè)參數(shù)是源數(shù)組名把兔,所以要傳遞的是value。

第二個(gè)參數(shù)是新數(shù)組長(zhǎng)度瓮顽,新數(shù)組長(zhǎng)度的值是通過(guò)newCapacity(int minCapacity)方法來(lái)計(jì)算并返回的值县好。

newCapacity(int minCapacity)方法的源碼:

private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

這個(gè)方法會(huì)返回一個(gè)新的容量大小(即新數(shù)組長(zhǎng)度)暖混,每次擴(kuò)容的容量大小是原來(lái)的容量的2倍加2缕贡。

最后

感謝你看到這里,看完有什么的不懂的可以在評(píng)論區(qū)問(wèn)我拣播,覺(jué)得文章對(duì)你有幫助的話(huà)記得給我點(diǎn)個(gè)贊晾咪,每天都會(huì)分享java相關(guān)技術(shù)文章或行業(yè)資訊,歡迎大家關(guān)注和轉(zhuǎn)發(fā)文章贮配!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谍倦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泪勒,更是在濱河造成了極大的恐慌昼蛀,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圆存,死亡現(xiàn)場(chǎng)離奇詭異叼旋,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)沦辙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)夫植,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人怕轿,你說(shuō)我怎么就攤上這事偷崩。” “怎么了撞羽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵阐斜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我诀紊,道長(zhǎng)谒出,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任邻奠,我火速辦了婚禮笤喳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碌宴。我一直安慰自己杀狡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布贰镣。 她就那樣靜靜地躺著呜象,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碑隆。 梳的紋絲不亂的頭發(fā)上恭陡,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音上煤,去河邊找鬼休玩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛劫狠,可吹牛的內(nèi)容都是我干的拴疤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嘉熊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼遥赚!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起阐肤,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凫佛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后孕惜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體愧薛,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年衫画,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了毫炉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡削罩,死狀恐怖瞄勾,靈堂內(nèi)的尸體忽然破棺而出费奸,到底是詐尸還是另有隱情,我是刑警寧澤进陡,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布愿阐,位于F島的核電站,受9級(jí)特大地震影響趾疚,放射性物質(zhì)發(fā)生泄漏缨历。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一糙麦、第九天 我趴在偏房一處隱蔽的房頂上張望辛孵。 院中可真熱鬧,春花似錦赡磅、人聲如沸魄缚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鲜滩。三九已至,卻和暖如春徙硅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搞疗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桩皿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓泄隔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親佛嬉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359