集合源碼(一)| ArrayList源碼剖析

學(xué)習(xí)源碼从橘,應(yīng)該是一件認(rèn)真與鉆研的功課,點(diǎn)滴積累。

package java.util;  
  
public class ArrayList<E> extends AbstractList<E>  
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable  
{  
    //
    private static final long serialVersionUID = 8683452581122892189L;  
  
    //  
    private static final int DEFAULT_CAPACITY = 10;  
  
    // 
    private static final Object[] EMPTY_ELEMENTDATA = {};  
  
    // 
    private transient Object[] elementData;  
  
    // 
    private int size;  
  
/**************** Constructor ***********************/  
  
    //
    public ArrayList(int initialCapacity) {  
        super();  
        if (initialCapacity < 0)  
            throw new IllegalArgumentException("Illegal Capacity: "+  
                                               initialCapacity);  

        this.elementData = new Object[initialCapacity];
    }  
    
    //
    public ArrayList() {  
        super();  
        this.elementData = EMPTY_ELEMENTDATA;
    }  
  
    //  
    public ArrayList(Collection<? extends E> c) {  
        elementData = c.toArray(); 
        size = elementData.length;  
         
        if (elementData.getClass() != Object[].class)  
            elementData = Arrays.copyOf(elementData, size, Object[].class);  
    }  
  
/******************* Array size *************/  
  
    //  
    public void trimToSize() {  
        modCount++;  
        //  
        if (size < elementData.length) {  
            elementData = Arrays.copyOf(elementData, size);  
        }  
    }  
  
    // 
    public void ensureCapacity(int minCapacity) {  
        int minExpand = (elementData != EMPTY_ELEMENTDATA)  
            // any size if real element table  
            ? 0  
            // larger than default for empty table. It's already supposed to be  
            // at default size.  
            : DEFAULT_CAPACITY;  
  
        if (minCapacity > minExpand) {  
            ensureExplicitCapacity(minCapacity);  
        }  
    }  
  
    private void ensureCapacityInternal(int minCapacity) {  
    //
        if (elementData == EMPTY_ELEMENTDATA) {  
        //  
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);  
        }  
    //  
        ensureExplicitCapacity(minCapacity);  
    }  
      
    //
    private void ensureExplicitCapacity(int minCapacity) {  
        modCount++; // 
  
        //  
        if (minCapacity - elementData.length > 0)  
            grow(minCapacity);  
    }  
  
    // 
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;  
  
    // 
    private void grow(int minCapacity) {  
        // overflow-conscious code  
        int oldCapacity = elementData.length;  
        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);  
    }  
  
    private static int hugeCapacity(int minCapacity) {  
        if (minCapacity < 0) // overflow  
            throw new OutOfMemoryError();  
        return (minCapacity > MAX_ARRAY_SIZE) ?  
            Integer.MAX_VALUE :  
            MAX_ARRAY_SIZE;  
    }  
  
    // 
    public int size() {  
        return size;  
    }  
  
    // 
    public boolean isEmpty() {  
        return size == 0;  
    }   
  
/****************************** Search Operations *************************/  
  
    // 
    public boolean contains(Object o) {  
        return indexOf(o) >= 0;  
    }  
  
    //  
    public int indexOf(Object o) {  
        if (o == null) {  
            for (int i = 0; i < size; i++)  
                if (elementData[i]==null)  
                    return i;  
        } else {  
            for (int i = 0; i < size; i++)  
                if (o.equals(elementData[i]))  
                    return i;  
        }  
        return -1;  
    }  
  
    // 
    public int lastIndexOf(Object o) {  
        if (o == null) {  
            for (int i = size-1; i >= 0; i--)  
                if (elementData[i]==null)  
                    return i;  
        } else {  
            for (int i = size-1; i >= 0; i--)  
                if (o.equals(elementData[i]))  
                    return i;  
        }  
        return -1;  
    }  
  
/******************************* Clone *********************************/  
  
    //克隆函數(shù)  
    public Object clone() {  
        try {  
            @SuppressWarnings("unchecked")  
                ArrayList<E> v = (ArrayList<E>) super.clone();  
        //將當(dāng)前ArrayList的全部元素拷貝到v中  
            v.elementData = Arrays.copyOf(elementData, size);  
            v.modCount = 0;  
            return v;  
        } catch (CloneNotSupportedException e) {  
            // this shouldn't happen, since we are Cloneable  
            throw new InternalError();  
        }  
    }  
  
/********************************* toArray *****************************/  
  
    /** 
    * 返回一個(gè)Object數(shù)組派继,包含ArrayList中所有的元素 
    * toArray()方法扮演著array-based和collection-based API之間的橋梁 
    */  
    public Object[] toArray() {  
        return Arrays.copyOf(elementData, size);  
    }  
  
    //返回ArrayList的模板數(shù)組  
    @SuppressWarnings("unchecked")  
    public <T> T[] toArray(T[] a) {  
    //如果數(shù)組a的大小 < ArrayList的元素個(gè)數(shù),  
    //則新建一個(gè)T[]數(shù)組捻艳,大小為ArrayList元素個(gè)數(shù)驾窟,并將“ArrayList”全部拷貝到新數(shù)組中。  
        if (a.length < size)  
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());  
  
    //如果數(shù)組a的大小 >= ArrayList的元素個(gè)數(shù)认轨,  
    //則將ArrayList全部拷貝到新數(shù)組a中绅络。  
        System.arraycopy(elementData, 0, a, 0, size);  
        if (a.length > size)  
            a[size] = null;  
        return a;  
    }  
  
/******************** Positional Access Operations ********************/  
  
    @SuppressWarnings("unchecked")  
    E elementData(int index) {  
        return (E) elementData[index];  
    }  
  
    //獲取index位置的元素值  
    public E get(int index) {  
        rangeCheck(index); //首先判斷index的范圍是否合法  
  
        return elementData(index);  
    }  
  
    //將index位置的值設(shè)為element,并返回原來(lái)的值  
    public E set(int index, E element) {  
        rangeCheck(index);  
  
        E oldValue = elementData(index);  
        elementData[index] = element;  
        return oldValue;  
    }  
  
    //將e添加到ArrayList中  
    public boolean add(E e) {  
        ensureCapacityInternal(size + 1);  // Increments modCount!!  
        elementData[size++] = e;  
        return true;  
    }  
  
    //將element添加到ArrayList的指定位置  
    public void add(int index, E element) {  
        rangeCheckForAdd(index);  
  
        ensureCapacityInternal(size + 1);  // Increments modCount!!  
    //將index以及index之后的數(shù)據(jù)復(fù)制到index+1的位置往后嘁字,即從index開(kāi)始向后挪了一位  
        System.arraycopy(elementData, index, elementData, index + 1,  
                         size - index);   
        elementData[index] = element; //然后在index處插入element  
        size++;  
    }  
  
    //刪除ArrayList指定位置的元素  
    public E remove(int index) {  
        rangeCheck(index);  
  
        modCount++;  
        E oldValue = elementData(index);  
  
        int numMoved = size - index - 1;  
        if (numMoved > 0)  
        //向左挪一位恩急,index位置原來(lái)的數(shù)據(jù)已經(jīng)被覆蓋了  
            System.arraycopy(elementData, index+1, elementData, index,  
                             numMoved);  
    //多出來(lái)的最后一位刪掉  
        elementData[--size] = null; // clear to let GC do its work  
  
        return oldValue;  
    }  
  
    //刪除ArrayList中指定的元素  
    public boolean remove(Object o) {  
        if (o == null) {  
            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的快速刪除與上面的public普通刪除區(qū)別在于,沒(méi)有進(jìn)行邊界判斷以及不返回刪除值  
    private void fastRemove(int index) {  
        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  
    }  
  
    //清空ArrayList纪蜒,將全部元素置為null  
    public void clear() {  
        modCount++;  
  
        // clear to let GC do its work  
        for (int i = 0; i < size; i++)  
            elementData[i] = null;  
  
        size = 0;  
    }  
  
    //將集合C中所有的元素添加到ArrayList中  
    public boolean addAll(Collection<? extends E> c) {  
        Object[] a = c.toArray();  
        int numNew = a.length;  
        ensureCapacityInternal(size + numNew);  // Increments modCount  
    //在原來(lái)數(shù)組的后面添加c中所有的元素  
        System.arraycopy(a, 0, elementData, size, numNew);  
        size += numNew;  
        return numNew != 0;  
    }  
  
    //從index位置開(kāi)始衷恭,將集合C中所欲的元素添加到ArrayList中  
    public boolean addAll(int index, Collection<? extends E> c) {  
        rangeCheckForAdd(index);  
  
        Object[] a = c.toArray();  
        int numNew = a.length;  
        ensureCapacityInternal(size + numNew);  // Increments modCount  
  
        int numMoved = size - index;  
        if (numMoved > 0)  
        //將index開(kāi)始向后的所有數(shù)據(jù),向后移動(dòng)numNew個(gè)位置纯续,給新插入的數(shù)據(jù)騰出空間  
            System.arraycopy(elementData, index, elementData, index + numNew,  
                             numMoved);  
    //將集合C中的數(shù)據(jù)插到剛剛騰出的位置  
        System.arraycopy(a, 0, elementData, index, numNew);  
        size += numNew;  
        return numNew != 0;  
    }  
  
    //刪除從fromIndex到toIndex之間的數(shù)據(jù)随珠,不包括toIndex位置的數(shù)據(jù)  
    protected void removeRange(int fromIndex, int toIndex) {  
        modCount++;  
        int numMoved = size - toIndex;  
        System.arraycopy(elementData, toIndex, elementData, fromIndex,  
                         numMoved);  
  
        // clear to let GC do its work  
        int newSize = size - (toIndex-fromIndex);  
        for (int i = newSize; i < size; i++) {  
            elementData[i] = null;  
        }  
        size = newSize;  
    }  
      
    //范圍檢測(cè)  
    private void rangeCheck(int index) {  
        if (index >= size)  
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
    }  
  
    //add和addAll方法中的范圍檢測(cè)  
    private void rangeCheckForAdd(int index) {  
        if (index > size || index < 0)  
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));  
    }  
  
    private String outOfBoundsMsg(int index) {  
        return "Index: "+index+", Size: "+size;  
    }  
  
    //刪除ArrayList中所有集合C中包含的數(shù)據(jù)  
    public boolean removeAll(Collection<?> c) {  
        return batchRemove(c, false);  
    }  
  
    //刪除ArrayList中除了集合C中包含的數(shù)據(jù)外的其他所有數(shù)據(jù)  
    public boolean retainAll(Collection<?> c) {  
        return batchRemove(c, true);  
    }  
      
    //批量刪除  
    private boolean batchRemove(Collection<?> c, boolean complement) {  
        final Object[] elementData = this.elementData;  
        int r = 0, w = 0;  
        boolean modified = false;  
        try {  
            for (; r < size; r++)  
                if (c.contains(elementData[r]) == complement)  
                    elementData[w++] = elementData[r];  
        } finally {  
            // Preserve behavioral compatibility with AbstractCollection,  
            // even if c.contains() throws.  
        //官方的注釋是為了保持和AbstractCollection的兼容性  
        //我的理解是上面c.contains拋出了異常,導(dǎo)致for循環(huán)終止杆烁,那么必然會(huì)導(dǎo)致r != size  
        //所以0-w之間是需要保留的數(shù)據(jù)牙丽,同時(shí)從w索引開(kāi)始將剩下沒(méi)有循環(huán)的數(shù)據(jù)(也就是從r開(kāi)始的)拷貝回來(lái),也保留  
            if (r != size) {  
                System.arraycopy(elementData, r,  
                                 elementData, w,  
                                 size - r);  
                w += size - r;  
            }  
        //for循環(huán)完畢兔魂,檢測(cè)了所有的元素  
        //0-w之間保存了需要留下的數(shù)據(jù)烤芦,w開(kāi)始以及后面的數(shù)據(jù)全部清空  
            if (w != size) {  
                // clear to let GC do its work  
                for (int i = w; i < size; i++)  
                    elementData[i] = null;  
                modCount += size - w;  
                size = w;  
                modified = true;  
            }  
        }  
        return modified;  
    }  
  
/***************************** Writer and Read Object *************************/  
  
    //java.io.Serializable的寫(xiě)入函數(shù)  
    //將ArrayList的“容量、所有的元素值”都寫(xiě)入到輸出流中  
    private void writeObject(java.io.ObjectOutputStream s)  
        throws java.io.IOException{  
        // Write out element count, and any hidden stuff  
        int expectedModCount = modCount;  
        s.defaultWriteObject();  
  
        // Write out size as capacity for behavioural compatibility with clone()  
    //寫(xiě)入“數(shù)組的容量”析校,保持與clone()的兼容性  
        s.writeInt(size);  
  
        //寫(xiě)入“數(shù)組的每一個(gè)元素”  
        for (int i=0; i<size; i++) {  
            s.writeObject(elementData[i]);  
        }  
  
        if (modCount != expectedModCount) {  
            throw new ConcurrentModificationException();  
        }  
    }  
  
    //java.io.Serializable的讀取函數(shù):根據(jù)寫(xiě)入方式讀出  
    private void readObject(java.io.ObjectInputStream s)  
        throws java.io.IOException, ClassNotFoundException {  
        elementData = EMPTY_ELEMENTDATA;  
  
        // Read in size, and any hidden stuff  
        s.defaultReadObject();  
  
        //從輸入流中讀取ArrayList的“容量”  
        s.readInt(); // ignored  
  
        if (size > 0) {  
            // be like clone(), allocate array based upon size not capacity  
            ensureCapacityInternal(size);  
  
            Object[] a = elementData;  
            //從輸入流中將“所有元素值”讀出  
            for (int i=0; i<size; i++) {  
                a[i] = s.readObject();  
            }  
        }  
    } 

關(guān)于ArrayList有以下幾點(diǎn)總結(jié):####

  • 動(dòng)態(tài)擴(kuò)充容量
    ArrayList在每次增加元素(可能是1個(gè)构罗,也可能是一組)時(shí)铜涉,都要調(diào)用該方法來(lái)確保足夠的容量。當(dāng)容量不足以容納當(dāng)前的元素個(gè)數(shù)時(shí)遂唧,就設(shè)置新的容量為舊的容量的1.5倍加1芙代,如果設(shè)置后的新容量還不夠,則直接新容量設(shè)置為傳入的參數(shù)(也就是所需的容量)盖彭,而后用Arrays.copyof()方法將元素拷貝到新的數(shù)組纹烹。從中可以看出,當(dāng)容量不夠時(shí)召边,每次增加元素铺呵,都要將原來(lái)的元素拷貝到一個(gè)新的數(shù)組中,非常之耗時(shí)隧熙,也因此建議在事先能確定元素?cái)?shù)量的情況下片挂,才使用ArrayList,否則建議使用LinkedList贞盯。

  • Arrays.copyOf()與System.copyOf()方法

    // Arrays.copyOf源碼
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            // 返回?cái)?shù)組組件的類(lèi)型
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        // 使用系統(tǒng)native函數(shù)音念,將數(shù)組復(fù)制到新數(shù)組中
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
  • ArrayList遍歷訪(fǎng)問(wèn)的效率
// 基于迭代器遍歷
Integer value = null;  
Iterator it = list.iterator();  
while (it.hasNext()) {  
    value = (Integer)it.next();  
}
// 基于隨機(jī)訪(fǎng)問(wèn)遍歷
Integer value = null;  
int size = list.size();  
for (int i = 0; i < size; i++) {  
    value = (Integer)list.get(i);          
}
// 基于增強(qiáng)for循環(huán)遍歷
Integer value = null;  
for (Integer integ : list) {  
    value = integ;  
}

三種方式遍歷,經(jīng)過(guò)測(cè)試躏敢,基于隨機(jī)訪(fǎng)問(wèn)(索引號(hào)的方式)闷愤,遍歷速度最快;ArrayList查找速度快件余,而插入和刪除速度較慢肝谭;

  • ArrayList支持null類(lèi)型
    在查找對(duì)象的索引號(hào),移除指定的對(duì)象時(shí)蛾扇,均進(jìn)行null類(lèi)型進(jìn)行檢查,可見(jiàn)ArrayList支持null類(lèi)型魏滚;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末镀首,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鼠次,更是在濱河造成了極大的恐慌更哄,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腥寇,死亡現(xiàn)場(chǎng)離奇詭異成翩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)赦役,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)麻敌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人掂摔,你說(shuō)我怎么就攤上這事术羔∮蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵级历,是天一觀的道長(zhǎng)释移。 經(jīng)常有香客問(wèn)我,道長(zhǎng)寥殖,這世上最難降的妖魔是什么玩讳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮嚼贡,結(jié)果婚禮上熏纯,老公的妹妹穿的比我還像新娘。我一直安慰自己编曼,他們只是感情好豆巨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掐场,像睡著了一般往扔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熊户,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天萍膛,我揣著相機(jī)與錄音,去河邊找鬼嚷堡。 笑死蝗罗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蝌戒。 我是一名探鬼主播串塑,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼北苟!你這毒婦竟也來(lái)了桩匪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤友鼻,失蹤者是張志新(化名)和其女友劉穎傻昙,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體彩扔,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妆档,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虫碉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贾惦。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纤虽,到底是詐尸還是另有隱情乳绕,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布逼纸,位于F島的核電站洋措,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杰刽。R本人自食惡果不足惜菠发,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贺嫂。 院中可真熱鬧滓鸠,春花似錦、人聲如沸第喳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)曲饱。三九已至悠抹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扩淀,已是汗流浹背楔敌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驻谆,地道東北人卵凑。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像胜臊,于是被迫代替她去往敵國(guó)和親勺卢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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

  • 一、基本數(shù)據(jù)類(lèi)型 注釋 單行注釋?zhuān)?/ 區(qū)域注釋?zhuān)?* */ 文檔注釋?zhuān)?** */ 數(shù)值 對(duì)于byte類(lèi)型而言...
    龍貓小爺閱讀 4,257評(píng)論 0 16
  • 一.線(xiàn)性表 定義:零個(gè)或者多個(gè)元素的有限序列织盼。也就是說(shuō)它得滿(mǎn)足以下幾個(gè)條件:??①該序列的數(shù)據(jù)元素是有限的。??②...
    Geeks_Liu閱讀 2,693評(píng)論 1 12
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法酱塔,類(lèi)相關(guān)的語(yǔ)法沥邻,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法羊娃,異常的語(yǔ)法唐全,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,598評(píng)論 18 399
  • Collection接口 Collection接口是所有集合的祖先類(lèi)。他有兩個(gè)構(gòu)造方法,一個(gè)無(wú)參構(gòu)造邮利,一個(gè)是帶Co...
    夜幕繁華閱讀 583評(píng)論 0 0
  • 前言 今天來(lái)介紹下ArrayList弥雹,在集合框架整體框架一章中,我們介紹了List接口延届,ArrayList繼承了A...
    嘟爺MD閱讀 4,444評(píng)論 6 31