ArrayList

一讯柔、ArrayList簡介

ArrayList是可以動態(tài)增長和縮減的索引序列抡蛙,它是基于數(shù)組實現(xiàn)的List類。

該類封裝了一個動態(tài)再分配的Object[]數(shù)組魂迄,每一個類對象都有一個capacity屬性粗截,表示它們所封裝的Object[]數(shù)組的長度,當(dāng)向ArrayList中添加元素時极祸,該屬性值會自動增加。如果想ArrayList中添加大量元素怠晴,可使用ensureCapacity方法一次性增加capacity遥金,可以減少增加重分配的次數(shù)提高性能。

ArrayList的用法和Vector向類似蒜田,但是Vector是一個較老的集合稿械,具有很多缺點,不建議使用冲粤。另外美莫,ArrayList和Vector的區(qū)別是:ArrayList是線程不安全的,當(dāng)多條線程訪問同一個ArrayList集合時梯捕,程序需要手動保證該集合的同步性厢呵,而Vector則是線程安全的。


二:源碼分析

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
  /**
    * Default initial capacity.默認初始容量
    */
private static final int DEFAULT_CAPACITY = 10;

/ **
  *  空數(shù)組
  */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
* 用于默認大小空實例的共享空數(shù)組實例傀顾。我們
* 將其與empty_elementdata區(qū)分開來襟铭,以了解在什么時候
* 第一個元素被添加。 
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
存儲ArrayList元素的數(shù)組緩沖區(qū)。
ArrayList的容量是這個數(shù)組緩沖區(qū)的長度寒砖。
一個空的ArrayList當(dāng) elementData==DEFAULTCAPACITY_EMPTY_ELEMENTDATA第一個元素被添加時赐劣,容量將擴展為DEFAULT_CAPACITY。
*/
transient Object[] elementData;

 /**
  * The size of the ArrayList (the number of elements it contains).
  *ArrayList的大辛ǘ肌(包含的元素個數(shù))
  * @serial
  */
private int size;

 /**
     * 用指定的初始容量構(gòu)造一個空列表魁兼。
     *
     * @param  initialCapacity 初始容量
     * @throws IllegalArgumentException 如果指定的初始容量是負的將拋出異常
     */
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);
        }
}

    /**
     * 構(gòu)造一個空列表,初始容量為10漠嵌。
     */
  public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  }

 /**
    構(gòu)造一個包含指定元素的列表的列表集合咐汞,按照集合的順序返回迭代器。
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

/**
將這個ArrayList實例的容量變成列表的當(dāng)前大小献雅。
應(yīng)用程序可以使用這個操作來最小化存儲一個ArrayList的實例碉考。
**/
 public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
  }

/**
增加這個ArrayList實例的容量,確保它至少能容納元素的數(shù)量
由最小容量參數(shù)指定挺身。
 @param   minCapacity   期望的最小容量
*/
  public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // 任何大小侯谁,如果不是默認元素表則為零
            ? 0
           //如果是默認的數(shù)組則為 DEFAULT_CAPACITY
            : DEFAULT_CAPACITY;
        //如果期望的最小容量比 minExpand大 則擴容
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
   }
 /**
   要分配的數(shù)組的最大大小。
    數(shù)組作為一個對象章钾,需要一定的內(nèi)存存儲對象頭信息墙贱,對象頭信息最大占用內(nèi)存不可超過8字節(jié),所以這里最大長度為 -8
    試圖分配更大的數(shù)組可能導(dǎo)致
     OutOfMemoryError:請求的數(shù)組大小超過VM限制
     */
  private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

 /**
       增加容量贱傀,以確保它至少可以容納
      由最小容量參數(shù)指定的元素數(shù)量惨撇。
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //新容量=old+old/2 ,即原來的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
      //當(dāng)容量超過MAX_ARRAY_SIZE,最大容量允許大于 MAX_ARRAY_SIZE
        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;
    }
   
 /**
     * 如果該列表包含指定的元素返回true
     * @param o element whose presence in this list is to be tested
     * @return <tt>true</tt> if this list contains the specified element
     */
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

 /**
     *添加一個元素府寒,ensureCapacityInternal(minCapacity)判斷最小容量和數(shù)組實際大小魁衙,如果最小容量比數(shù)組大則進行擴容為原來的1.5倍
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }


 /**
    移除下標的為index的元素
     *
     * @param index the index of the element to be removed
     * @return the element that was removed from the list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        rangeCheck(index);

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

        int numMoved = size - index - 1;
        if (numMoved > 0)
            //注意這里,將數(shù)組index以后的都向前移動一位
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //將數(shù)組最后一位置為null
        elementData[--size] = null; // clear to let GC do its work
        return oldValue;
    }

 /**
   移除指定元素:如果傳入的元素為空株搔,則刪除第一個出現(xiàn)的空元素剖淀,如果沒有空元素則返回 false
   如果傳入的不為空,則刪除第一個出現(xiàn)的元素纤房,不存在返回false
     *
     * @param o element to be removed from this list, if present
     * @return <tt>true</tt> if this list contained the specified element
     */
    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 remove method that skips bounds checking and does not
     * return the value removed.
     */
    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
    }

/**
     * 清空一個list
     * be empty after this call returns.
     */
    public void clear() {
        modCount++;
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纵隔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炮姨,更是在濱河造成了極大的恐慌捌刮,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舒岸,死亡現(xiàn)場離奇詭異绅作,居然都是意外死亡,警方通過查閱死者的電腦和手機蛾派,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門棚蓄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堕扶,“玉大人,你說我怎么就攤上這事梭依∩运悖” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵役拴,是天一觀的道長糊探。 經(jīng)常有香客問我,道長河闰,這世上最難降的妖魔是什么科平? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮姜性,結(jié)果婚禮上瞪慧,老公的妹妹穿的比我還像新娘。我一直安慰自己部念,他們只是感情好弃酌,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著儡炼,像睡著了一般妓湘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乌询,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天榜贴,我揣著相機與錄音,去河邊找鬼妹田。 笑死唬党,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鬼佣。 我是一名探鬼主播驶拱,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沮趣!你這毒婦竟也來了屯烦?” 一聲冷哼從身側(cè)響起坷随,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤房铭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后温眉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缸匪,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年类溢,在試婚紗的時候發(fā)現(xiàn)自己被綠了凌蔬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片露懒。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖砂心,靈堂內(nèi)的尸體忽然破棺而出懈词,到底是詐尸還是另有隱情,我是刑警寧澤辩诞,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布坎弯,位于F島的核電站,受9級特大地震影響译暂,放射性物質(zhì)發(fā)生泄漏抠忘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一外永、第九天 我趴在偏房一處隱蔽的房頂上張望崎脉。 院中可真熱鬧,春花似錦伯顶、人聲如沸囚灼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啦撮。三九已至,卻和暖如春汪厨,著一層夾襖步出監(jiān)牢的瞬間赃春,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工劫乱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留织中,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓衷戈,卻偏偏與公主長得像狭吼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子殖妇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

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