ArrayList源碼分析

簡書:capo
轉(zhuǎn)載請注明原創(chuàng)出處,謝謝充择!

今天,我們分析下JDK8中ArrayList的源碼,我們知道ArrayList是List接口的一個實(shí)現(xiàn),是一個動態(tài)擴(kuò)容的數(shù)組闽晦。那么它是怎樣在我們添加元素時實(shí)現(xiàn)動態(tài)擴(kuò)容的了?

這是數(shù)組定義的幾個成員變量


image.png

首先我們調(diào)用數(shù)組的 add(E e) 方法時,這里我用的是一個重載的方法,第一個參數(shù)指的是要添加元素的下標(biāo),默認(rèn)如果我們不提供這個參數(shù)的話是從數(shù)組的最后添加的。

public void add(int var1, E var2) {
        //檢查數(shù)組下標(biāo)
        this.rangeCheckForAdd(var1);
        //保證數(shù)組內(nèi)部容量 插入數(shù)組位置往后移動一個位置
        this.ensureCapacityInternal(this.size + 1);      
        //舊的數(shù)組就會使用Arrays.copyOf方法被復(fù)制到新的數(shù)組中,現(xiàn)有的數(shù)組指向了新的數(shù)組
        System.arraycopy(this.elementData, var1, this.elementData, var1 + 1, this.size - var1);
        this.elementData[var1] = var2;
        ++this.size;
    }

Java會檢查這個數(shù)組下標(biāo)是否超過這個數(shù)組的長度或者下標(biāo)小于0,如果是的話就拋出
IndexOutOfBoundsException異常

 private void rangeCheckForAdd(int var1) {
        if(var1 > this.size || var1 < 0) {
            throw new IndexOutOfBoundsException(this.outOfBoundsMsg(var1));
        }
    }

如果數(shù)組元素等于默認(rèn)空數(shù)組的話,那么數(shù)組插入數(shù)組索引下標(biāo)會進(jìn)行一個取最大值的操作

private void ensureCapacityInternal(int var1) {
       //如果添加的這個元素 == 默認(rèn)的空數(shù)組的第一個元素
        if(this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            var1 = Math.max(10, var1); //在數(shù)組初始容量和數(shù)組的下標(biāo)中取一個最大值
        }
        
        //明確保證數(shù)組的容量
        this.ensureExplicitCapacity(var1);
    }

為了明確保證數(shù)組容量序列化計(jì)算

private void ensureExplicitCapacity(int var1) {
         //反序列化計(jì)算器加 1 
        ++this.modCount;
        //如果要指定添加元素的下標(biāo)位置 > 數(shù)組長度  此時就要擴(kuò)容
        if(var1 - this.elementData.length > 0) {
            this.grow(var1);
        }

    }

計(jì)算新數(shù)組的長度=原始數(shù)組的1.5倍

private void grow(int var1) {
             
        int var2 = this.elementData.length;
        //新的數(shù)組長度 = 原始數(shù)組長度 + 原始數(shù)組 / 2
        int var3 = var2 + (var2 >> 1);
        //如果新的數(shù)組長度 < 要添加元素的位置
        if(var3 - var1 < 0) {
            var3 = var1;//新數(shù)組長度 = 添加元素的位置長度
        }
        
        //如果新的數(shù)組長度 > 2147483639 
        if(var3 - 2147483639 > 0) {
            var3 = hugeCapacity(var1); //就判斷是否超過了JVM內(nèi)存
        }

        this.elementData = Arrays.copyOf(this.elementData, var3);
    }

判斷這個新數(shù)組長度是否JVM內(nèi)存分配的最大值

private static int hugeCapacity(int var0) {
        if(var0 < 0) {
            throw new OutOfMemoryError();
        } else {
            return var0 > 2147483639?2147483647:2147483639;
        }
    }

總結(jié)一下:

  • ArrayList底層是一個動態(tài)擴(kuò)容的數(shù)
  • 數(shù)組的初始長度是10個單位
  • 如果指定了要添加元素的索引下標(biāo)的話提岔,如果這個數(shù)組元素默認(rèn)初始空數(shù)組的話就取一個最小值(添加元素的下標(biāo)索引)
  • 擴(kuò)容后新數(shù)組的長度 = 原始數(shù)組長度 + 原始數(shù)組長度/2 (也就是原始數(shù)組長度的1.5倍)
  • 數(shù)組的長度不是沒有上限的,如果超過2147483639就會報(bào)OOM
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仙蛉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子碱蒙,更是在濱河造成了極大的恐慌荠瘪,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赛惩,死亡現(xiàn)場離奇詭異哀墓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)喷兼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門篮绰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人季惯,你說我怎么就攤上這事吠各。” “怎么了勉抓?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵贾漏,是天一觀的道長。 經(jīng)常有香客問我琳状,道長磕瓷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任念逞,我火速辦了婚禮困食,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翎承。我一直安慰自己硕盹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布叨咖。 她就那樣靜靜地躺著瘩例,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甸各。 梳的紋絲不亂的頭發(fā)上垛贤,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音趣倾,去河邊找鬼聘惦。 笑死,一個胖子當(dāng)著我的面吹牛儒恋,可吹牛的內(nèi)容都是我干的善绎。 我是一名探鬼主播黔漂,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼禀酱!你這毒婦竟也來了炬守?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剂跟,失蹤者是張志新(化名)和其女友劉穎减途,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浩聋,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡观蜗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了衣洁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡抖仅,死狀恐怖坊夫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撤卢,我是刑警寧澤环凿,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站放吩,受9級特大地震影響智听,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渡紫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一到推、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惕澎,春花似錦莉测、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至八孝,卻和暖如春董朝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背干跛。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工子姜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驯鳖。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓闲询,卻偏偏與公主長得像久免,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子扭弧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

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

  • ArrayList是在Java中最常用的集合之一阎姥,其本質(zhì)上可以當(dāng)做是一個可擴(kuò)容的數(shù)組,可以添加重復(fù)的數(shù)據(jù)鸽捻,也支持隨...
    ShawnIsACoder閱讀 572評論 4 7
  • 概述 在分析ArrayList源碼之前呼巴,先看一下ArrayList在數(shù)據(jù)結(jié)構(gòu)中的位置,常見的數(shù)據(jù)結(jié)構(gòu)按照邏輯結(jié)構(gòu)跟...
    wustor閱讀 565評論 4 2
  • ArrayList 認(rèn)識 ArrayList是最常見以及每個Java開發(fā)者最熟悉的集合類了 elementData...
    zlb閱讀 151評論 0 0
  • 每個 ArrayList 實(shí)例都有一個容量御蒲,該容量是指用來存儲列表元素的數(shù)組的大小衣赶。它總是至少等于列表的大小。隨著...
    Mervyn_2014閱讀 195評論 0 0
  • 定義 除了實(shí)現(xiàn)了List接口厚满,還實(shí)現(xiàn)了RandomAccess府瞄,Cloneable, java.io.Serial...
    zhanglbjames閱讀 430評論 0 0