ArrayList分析

超殺女.jpg

對于集合的源碼分析发皿,一般我會采用這幾種方式

  1. 怎么添加元素?
  2. 怎么獲取元素拂蝎?
  3. 怎么刪除元素穴墅?
  4. 內(nèi)部數(shù)據(jù)結構實現(xiàn)?

話不多說,直接走起玄货。

一.怎么添加元素皇钞?

一般我們通過ArrayList添加元素。一般會調(diào)用其構造方法,然后調(diào)用其對象的add方法

查看空參構造函數(shù)

//Constructs an empty list with an initial capacity of ten.
 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

通過構造函數(shù)可以發(fā)現(xiàn)松捉。ArrayList在調(diào)用無參的構造函數(shù)時夹界,會構造一個長度為10的緩存數(shù)組

查看add方法

public boolean add(E e) {
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }

通過該方法發(fā)現(xiàn) ArralyList內(nèi)部的數(shù)據(jù)結構其實是一個數(shù)組(elementData[size++] = e;)并且在添加時會先判斷當前容器在添加了一個對象之后該對象的容納能力(主要為了,在下一次添加元素的時候隘世,緩存數(shù)組能夠有足夠的空間添加元素)可柿。之后將元素添加到數(shù)組末尾。

繼續(xù)查看ensureCapacityInternal()方法

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

這里我們發(fā)現(xiàn)丙者,如果當前elementData為空的話复斥,minCapacity=DEFAULT_CAPACITY,同時DEFAULT_CAPACITY的默認值是10,從這我們可以看出,在第一次初始化的時候械媒,ArrayList內(nèi)部會默認創(chuàng)建一個內(nèi)部長度為10的數(shù)組目锭。

繼續(xù)點擊ensureExplicitCapacity()方法

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        //判斷添加元素后,緩存數(shù)組時候需要擴展
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

該方法會記錄當前數(shù)組的更改次數(shù)纷捞,并且判斷當前數(shù)組添加后痢虹,是否需要進行增長,

繼續(xù)走grow方法(重點的來了@夹濉J婪帧!)

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //擴展數(shù)組的長度缀辩,
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

該方法會擴展緩存為當前數(shù)組的長度為 原數(shù)組長度+原數(shù)組長度的二分之一臭埋,也就是按照原數(shù)組的50%進行增長,同時該數(shù)組最大的擴展長度是Integer.MAX_VALUE - 8臀玄。也就是ArrayList最多能存儲的數(shù)據(jù)長度瓢阴,通過擴展數(shù)組長度以后,在下一次添加數(shù)據(jù)的時候健无,ArrayList就有足夠的空間去添加新的元素了荣恐。

二.怎么獲取元素

其實ArrayList獲取其中的元素很簡單,根據(jù)角標獲取對應數(shù)組中的元素累贤,具體代碼如下:

 public E get(int index) {
        if (index >= size)//判斷當前角標長度是否超過數(shù)組長度叠穆,如果是拋出異常,反之返回數(shù)據(jù)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        return (E) elementData[index];
    }

三.怎么刪除元素

在ArrayList中臼膏,有兩個關于刪除元素的方法硼被,一個是remove(int),另一個是remove(Object)

1.remove(int)方法

public E remove(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

        modCount++;
        E oldValue = (E) elementData[index];

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // 將數(shù)組最后一位置null

        return oldValue;
    }

這里先判斷刪除角標是否超過數(shù)組長度,然后通過System.arrayCopty()方法將角標對應的元素刪除渗磅。

這里對System.arrayCopty()方法解釋一下嚷硫。該方法的第一個參數(shù)是源數(shù)組检访,第二個參數(shù)是復制的開始角標,第二個參數(shù)是目標數(shù)組仔掸。第三個參數(shù)是目標數(shù)組源數(shù)組的復制數(shù)據(jù)開始角標脆贵。最后一個參數(shù)是復制的長度。(注意:F鹉骸B舭薄!復制的長度不能大于目標數(shù)組減去開始角標的長度源數(shù)組減去開始角標的長度)

eg:

  int[] a = {0, 1, 2, 3, 4};
  int[] b = {5, 6, 7, 8, 9};
  System.arraycopy(a, 0, b, 1, 3);
 // 則進行操作后 b = {5鞋怀,0,1,2,9} 

2.remove(Object)方法

 public boolean remove(Object o) {
        if (o == null) {//判斷當前元素是否為空双泪,遍歷數(shù)組,獲取其角標
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

  private void fastRemove(int index) {//根據(jù)角標密似,刪除相應元素
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

remove(Object)根據(jù)object在數(shù)組的角標,執(zhí)行fastRemove(index)方法葫盼。刪除方法與remoIndex(int)一樣残腌。這里就不在分析了。

總結

  • ArrayList內(nèi)部實現(xiàn)是數(shù)組贫导,且當數(shù)組長度不夠時抛猫,數(shù)組的會進行原數(shù)組長度的1.5倍擴容
  • ArrayList內(nèi)部元素是可以重復的孩灯。且有序的闺金,因為是按照數(shù)組一個一個進行添加的。
  • ArrayList是線程不安全的峰档,因為其內(nèi)部添加败匹、刪除、等操作讥巡,沒有進行同步操作掀亩。
  • ArrayList增刪元素速度較慢,因為內(nèi)部實現(xiàn)是數(shù)組欢顷,每次操作都會對數(shù)組進行復制操作槽棍,復制操作是比較耗時的

最后,附上我寫的一個基于Kotlin 仿開眼的項目SimpleEyes(ps: 其實在我之前抬驴,已經(jīng)有很多小朋友開始仿這款應用了炼七,但是我覺得要做就做好。所以我的項目和其他的人應該不同布持,不僅僅是簡單的一個應用豌拙。但是,但是鳖链。但是姆蘸。重要的話說三遍墩莫。還在開發(fā)階段,不要打我)逞敷,歡迎大家follow和start

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狂秦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子推捐,更是在濱河造成了極大的恐慌裂问,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牛柒,死亡現(xiàn)場離奇詭異堪簿,居然都是意外死亡,警方通過查閱死者的電腦和手機皮壁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門椭更,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛾魄,你說我怎么就攤上這事虑瀑。” “怎么了滴须?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵舌狗,是天一觀的道長。 經(jīng)常有香客問我扔水,道長痛侍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任魔市,我火速辦了婚禮主届,結果婚禮上,老公的妹妹穿的比我還像新娘嘹狞。我一直安慰自己岂膳,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布磅网。 她就那樣靜靜地躺著谈截,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涧偷。 梳的紋絲不亂的頭發(fā)上簸喂,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音燎潮,去河邊找鬼喻鳄。 笑死,一個胖子當著我的面吹牛确封,可吹牛的內(nèi)容都是我干的除呵。 我是一名探鬼主播再菊,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼颜曾!你這毒婦竟也來了纠拔?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤泛豪,失蹤者是張志新(化名)和其女友劉穎稠诲,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诡曙,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡臀叙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了价卤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劝萤。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖慎璧,靈堂內(nèi)的尸體忽然破棺而出稳其,到底是詐尸還是另有隱情,我是刑警寧澤炸卑,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站煤傍,受9級特大地震影響盖文,放射性物質發(fā)生泄漏。R本人自食惡果不足惜蚯姆,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一五续、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧龄恋,春花似錦疙驾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至显押,卻和暖如春扳肛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乘碑。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工挖息, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兽肤。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓套腹,卻偏偏與公主長得像绪抛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子电禀,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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

  • 一.線性表 定義:零個或者多個元素的有限序列幢码。也就是說它得滿足以下幾個條件:??①該序列的數(shù)據(jù)元素是有限的。??②...
    Geeks_Liu閱讀 2,701評論 1 12
  • 標簽(空格分隔): java 上一篇文章我們簡單的對java集合框架有了一個簡單的認識鞭呕,本次蛤育,我們來具體的探討一下...
    Sivin閱讀 457評論 2 4
  • ArrayList是在Java中最常用的集合之一,其本質上可以當做是一個可擴容的數(shù)組葫松,可以添加重復的數(shù)據(jù)瓦糕,也支持隨...
    ShawnIsACoder閱讀 572評論 4 7
  • 藍色經(jīng)典初相遇, 一見馬桶誤終身腋么。 只恨我生君已吐咕娄, 黑木崖前憶手環(huán)。 故事就是故事珊擂,現(xiàn)實就是現(xiàn)實圣勒,對于一...
    革米軒閱讀 253評論 0 1
  • 我該如何拯救我那被狗吃了的青春?我該如何回憶摧扇?我該如何控訴圣贸?我該如何懺悔? 總有一個時刻扛稽,我們的防線被一擊而破吁峻。曾...
    是京京呀閱讀 266評論 1 2