ArrayList

ArrayList只寫add方法了赂蠢,其他的方法感興趣的自己看一下幔戏,都比較簡單拼卵。

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

public ArrayList(int initialCapacity) {
        // 如果初始容量大于0,則創(chuàng)建一個initialCapacity大小的數(shù)組
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            // 初始容量等于0惠啄,則用初始數(shù)組
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

// 無參構(gòu)造函數(shù),用默認數(shù)組合敦,并且默認的的容量是10
 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

public ArrayList(Collection<? extends E> c) {
       // elementData被賦值為元素數(shù)組
        elementData = c.toArray();
       // 元素個數(shù)(size)被賦值為elementData的長度
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                // 數(shù)組拷貝
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

添加元素

需要的常量

   // 默認數(shù)組
   private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};    
   // 默認容量
   private static final int DEFAULT_CAPACITY = 10;
   // 數(shù)組的最大容量
   private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 public boolean add(E e) {
        // 調(diào)整容量
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 調(diào)整完容量加入元素
        elementData[size++] = e;
        return true;
    }


 // 調(diào)整容量
 private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

// 計算添加元素所需要的最小容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
         // 如果是第一次add牲迫,則返回默認容量和當(dāng)前minCapacity的最大值
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
      // 若不是第一次add,則返回minCapacity
        return minCapacity;
    }

// 調(diào)整容量
private void ensureExplicitCapacity(int minCapacity) {
        // 修改次數(shù)自增
        modCount++;

         // 若添加元素所需的容量比當(dāng)前數(shù)組長度小了衡楞,則擴容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

// 真正擴容
private void grow(int minCapacity) {
        // 原容量
        int oldCapacity = elementData.length;
        // 新容量是原容量的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
       // 新容量還是不夠吱雏,那么新容量就等于minCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 新容量溢出了
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 拷貝一個新數(shù)組
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
  
// 容量溢出處理
 private static int hugeCapacity(int minCapacity) {
        // 已經(jīng)超出int范圍了,拋OutOfMemoryError
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        // 沒超出返回新容量
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

minCapacity代表添加元素所需要的容量,等于原容量+添加的元素個數(shù)

Q&A

Q:最大數(shù)組容量MAX_ARRAY_SIZE為啥是 Integer.MAX_VALUE - 8歧杏?
A:數(shù)組作為一個對象镰惦,需要一定的內(nèi)存存儲對象頭信息,對象頭信息最大占用內(nèi)存不可超過8字節(jié)犬绒。

最后一點需要注意的

java.util包下的集合為啥都不支持增強for或者迭代器迭代修改集合旺入?
答案在ArrayList的迭代器代碼中找。

private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            // 注意
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                // 注意
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

????可以看到每次調(diào)用迭代器的next方法獲取下一個元素的時候凯力,總是會執(zhí)行checkForComodification茵瘾,這個方法會對比modCount和expectedModCount是否一致,如果不一致則拋出ConcurrentModificationException咐鹤。而add拗秘、remove、clear等方法都會修改modCount的值祈惶。
????調(diào)用迭代的remove方法則不會有這個問題聘殖,因為每次remove都會更新expectedModCount的值

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市行瑞,隨后出現(xiàn)的幾起案子奸腺,更是在濱河造成了極大的恐慌,老刑警劉巖血久,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件突照,死亡現(xiàn)場離奇詭異,居然都是意外死亡氧吐,警方通過查閱死者的電腦和手機讹蘑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筑舅,“玉大人座慰,你說我怎么就攤上這事〈浼穑” “怎么了版仔?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長误墓。 經(jīng)常有香客問我蛮粮,道長,這世上最難降的妖魔是什么谜慌? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任然想,我火速辦了婚禮,結(jié)果婚禮上欣范,老公的妹妹穿的比我還像新娘变泄。我一直安慰自己令哟,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布妨蛹。 她就那樣靜靜地躺著励饵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滑燃。 梳的紋絲不亂的頭發(fā)上役听,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音表窘,去河邊找鬼典予。 笑死,一個胖子當(dāng)著我的面吹牛乐严,可吹牛的內(nèi)容都是我干的瘤袖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼昂验,長吁一口氣:“原來是場噩夢啊……” “哼捂敌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起既琴,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤占婉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后甫恩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逆济,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年磺箕,在試婚紗的時候發(fā)現(xiàn)自己被綠了奖慌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡松靡,死狀恐怖简僧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雕欺,我是刑警寧澤岛马,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站阅茶,受9級特大地震影響蛛枚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脸哀,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望扭吁。 院中可真熱鬧撞蜂,春花似錦盲镶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至浦旱,卻和暖如春宇色,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颁湖。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工宣蠕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甥捺。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓抢蚀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镰禾。 傳聞我的和親對象是個殘疾皇子皿曲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354

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