java集合之ArrayList源碼解析

ArrayList 繼承結(jié)構(gòu)

ArrayLisy.png

ArrayList的本質(zhì)是一個(gè)數(shù)組

這是ArrayList的屬性减俏,包括默認(rèn)長度幼苛,空數(shù)組倔喂,elementData(存儲(chǔ)數(shù)據(jù)的數(shù)組)和size(集合中元素個(gè)數(shù))

   private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

ArrayList的構(gòu)造函數(shù)

  1. 無參夠著函數(shù)雏蛮,就是初始化為一個(gè)默認(rèn)空數(shù)組恢氯,不分配內(nèi)存空間带斑,實(shí)現(xiàn)懶加載,需要的時(shí)候再分配內(nèi)存
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
  1. 有參構(gòu)造函數(shù)勋拟,出入初始化大小勋磕,檢查初始參數(shù)
  2. 大于0:分配對(duì)應(yīng)內(nèi)存空間
  3. 等于0:賦值給默認(rèn)空數(shù)組
  4. 小于0: 拋出初始化參數(shù)異常
 public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

重要方法分析:add(E e) , get(int index), set(int index , T data), remove(int index)

  • add(E e): 添加一個(gè)數(shù)據(jù)
    ensureCapacityInternal(size + 1): 確認(rèn)容量
    minCapacity -> size+1
    calculateCapacity(elementData, minCapacity):計(jì)算容量,如果插入后size大于當(dāng)前數(shù)組的容量則擴(kuò)容敢靡,如果size小于挂滓,直接返回,執(zhí)行賦值操作啸胧,同時(shí)size+1
    grow(minCapacity): 擴(kuò)容方法
 private void grow(int minCapacity) {
        // 獲取原來數(shù)組的容量
        int oldCapacity = elementData.length;
       // 擴(kuò)容1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
       // 主要用于第一次插入時(shí)擴(kuò)容赶站,默認(rèn)為10,所以第一次不是擴(kuò)1.5倍纺念,而是創(chuàng)建長度為10的數(shù)組
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
      // 判斷數(shù)組長度是否超過最大值
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 將老數(shù)據(jù)拷貝到一個(gè)新數(shù)組
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
  • get(int index)
public E get(int index) {
        // 數(shù)組下標(biāo)越界檢查
        rangeCheck(index);
        return elementData(index);
    }
  • set(int index, T data)
public E set(int index, E element) {
        // 數(shù)組下標(biāo)越界檢查
        rangeCheck(index);
        E oldValue = elementData(index);
        // 賦值
        elementData[index] = element;
       // 返回舊值
        return oldValue;
    }
  • remove(int index)
public E remove(int index) {
        // 數(shù)組下標(biāo)越界檢查
        rangeCheck(index);
        modCount++;
        E oldValue = elementData(index);
        // 計(jì)算需要移動(dòng)的數(shù)量贝椿,如果是最末尾賊不要移動(dòng)
        int numMoved = size - index - 1;
       // 如果在非末尾
        if (numMoved > 0)
          //  將當(dāng)前索引所在的后面的所有值,向前移動(dòng)一位(拷貝index+1到最后的所有數(shù)據(jù)到index開始的位置)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        // 將最后一位設(shè)置為空陷谱,同時(shí)size-1
        elementData[--size] = null; // clear to let GC do its work
       // 返回舊值
        return oldValue;
    }

源碼中modCount++的作用

用于在多線程環(huán)境下烙博,保證數(shù)據(jù)安全的FailFast機(jī)制。主要是在集合迭代過程中,防止集合變化導(dǎo)致錯(cuò)誤渣窜。原理是集合開始迭代是會(huì)把modCount賦值給迭代器一個(gè)屬性铺根,迭代過程中不斷檢查值當(dāng)前modCount與原始值是否相等,不等則拋出ConcurrentModificationException異常

總結(jié)

  1. ArrayList的實(shí)現(xiàn)是數(shù)組乔宿,底層結(jié)構(gòu)是連續(xù)內(nèi)存空間的線性表夷都,在隨機(jī)讀寫上性能好,通過計(jì)算獲取下標(biāo)位置
  2. 在隨機(jī)插入和刪除時(shí)予颤, 需要移動(dòng)插入位置后面的所有元素囤官,性能較差
  3. 在插入時(shí)可能需要?jiǎng)討B(tài)擴(kuò)容,第一次擴(kuò)容到10蛤虐,后面每次擴(kuò)容1.5倍
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末党饮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子驳庭,更是在濱河造成了極大的恐慌刑顺,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饲常,死亡現(xiàn)場(chǎng)離奇詭異蹲堂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贝淤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門柒竞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人播聪,你說我怎么就攤上這事朽基。” “怎么了离陶?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵稼虎,是天一觀的道長。 經(jīng)常有香客問我招刨,道長霎俩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任沉眶,我火速辦了婚禮打却,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沦寂。我一直安慰自己学密,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布传藏。 她就那樣靜靜地躺著腻暮,像睡著了一般彤守。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哭靖,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天具垫,我揣著相機(jī)與錄音,去河邊找鬼试幽。 笑死筝蚕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铺坞。 我是一名探鬼主播起宽,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼济榨!你這毒婦竟也來了坯沪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤擒滑,失蹤者是張志新(化名)和其女友劉穎腐晾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丐一,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡藻糖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了库车。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巨柒。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凝颇,靈堂內(nèi)的尸體忽然破棺而出潘拱,到底是詐尸還是另有隱情,我是刑警寧澤拧略,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瘪弓,受9級(jí)特大地震影響垫蛆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腺怯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一袱饭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧呛占,春花似錦虑乖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仅叫。三九已至,卻和暖如春糙捺,著一層夾襖步出監(jiān)牢的瞬間诫咱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國打工洪灯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坎缭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓签钩,卻偏偏與公主長得像掏呼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铅檩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者憎夷,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn)柠并,也就放棄了無數(shù)的可能岭接。 ...
    yichen大刀閱讀 6,052評(píng)論 0 4
  • 公元:2019年11月28日19時(shí)42分農(nóng)歷:二零一九年 十一月 初三日 戌時(shí)干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 6,879評(píng)論 0 2
  • 今天上午陪老媽看病,下午健身房跑步臼予,晚上想想今天還沒有斷舍離鸣戴,馬上做,衣架和旁邊的的布衣架粘拾,一看亂亂窄锅,又想想自己是...
    影子3623253閱讀 2,913評(píng)論 1 8