2019-12-04 Java-ArrayList 擴容機制 以及 add方法 remove方法 核心代碼解讀

@[TOC](Java-ArrayList 擴容機制 以及 add方法 remove方法 核心代碼解讀)

1常侦、創(chuàng)建MyArrayList類

public class MyArrayList {
}

2、構(gòu)造方法

先看 JDK中ArrayList的構(gòu)造方法

    /**
     * Constructs an empty list with the specified initial capacity.
     * 使用指定的容量長度 構(gòu)造一個空list坡倔。
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            // 如果傳入的初始化容量大于0 就用初始化容量初始化內(nèi)部數(shù)組
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            // 如果初始化容量 等于0 就使用默認的空元素數(shù)據(jù)來做初始化
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 其他的容量長度是不合法的
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     * 使用一個默認的初始化容量10 構(gòu)造一個空list, 這應(yīng)該是jdk1.8之前 會在構(gòu)造函數(shù)中直接初始化內(nèi)部數(shù)組 1.8之后做了修改 放到了add方法中初始化垢袱。
     * (但是好像實現(xiàn)中并沒有在構(gòu)造方法中使用默認的數(shù)組長度10來初始化內(nèi)部數(shù)組请契,而是直接使用了DEFAULTCAPACITY_EMPTY_ELEMENTDATA )
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

jdk 中的兩個最重要的構(gòu)造方法如上爽锥。
其中有幾個重要的參數(shù)

    // 內(nèi)部數(shù)組
    private Object[] elementData;

    // 默認數(shù)組容量
    private static final int DEFAULT_CAPACITY = 10;

    // 用于空實例的共享空數(shù)組實例
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 共享空數(shù)組實例,用于默認大小的空實例腮考。我們將其與EMPTY_ELEMENTDATA區(qū)分開來踩蔚,以了解添加第一個元素時應(yīng)該膨脹多少馅闽。
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    //ArrayList的大小(它包含的元素的數(shù)量)福也。
    private int size;

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

參考jdk ArrayList 的構(gòu)造方法 實現(xiàn)MyArrayList的構(gòu)造方法

  // 1. 構(gòu)造方法 初始化內(nèi)部數(shù)組
    public MyArrayList(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);
        }
    }

    // 1. 構(gòu)造方法 初始化內(nèi)部數(shù)組
    public MyArrayList(){
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

2.1ArrayList最多可以存放多少個元素峦甩?

從字段
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
可以看出來 最大值就是Integer的最大值
Integer的范圍是
因為最左邊的一位是符號位 所以剩下31位可以表達數(shù)值
JDK源碼中的寫法

   /**
     * A constant holding the minimum value an {@code int} can
     * have, -2<sup>31</sup>.
     */
    @Native public static final int   MIN_VALUE = 0x80000000;

    /**
     * A constant holding the maximum value an {@code int} can
     * have, 2<sup>31</sup>-1.
     */
    @Native public static final int   MAX_VALUE = 0x7fffffff;

3穴店、add方法的實現(xiàn)

參考JDK ArrayList add方法實現(xiàn)
1.確定容量大小(這一步包含內(nèi)部數(shù)組擴容機制)
2.elementData持有傳入的元素
3.處理完成后返回true

     // 2. add方法
    public Boolean add(Object ele){

        // 2.1確定內(nèi)部數(shù)組的容量大小 判斷是否需要擴容(如果是默認無參數(shù)構(gòu)造方法生成的對象,在第一次add的時候會初始化內(nèi)部數(shù)組)
        ensureCapacityInternal(size + 1); // 這里傳入的參數(shù)是 內(nèi)置數(shù)組應(yīng)該有的最小值

        // 保存元素到數(shù)組中
        elementData[size++] = ele;

        return true;
    }

     // 2.1 確定數(shù)組的長度
    private void ensureCapacityInternal(int minCapacity) {
        // 判斷是否是使用默認無參數(shù)構(gòu)造方法來創(chuàng)建的arraylist
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 如果是的話 對比需要的最小數(shù)組長度和默認數(shù)組長度 獲取到其中的最大值 作為內(nèi)部數(shù)組的最小長度
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 2.1.1明確數(shù)組長度
        ensureExplicitCapacity(minCapacity);
    }
    
    // 2.1.1明確數(shù)組長度 參數(shù)是數(shù)組應(yīng)有的最小容量長度
    private void ensureExplicitCapacity(int minCapacity) {

        // overflow-conscious code
        // 如果數(shù)組需要的最小值 大于當(dāng)前數(shù)組的長度 則數(shù)組需要擴容
        if (minCapacity - elementData.length > 0){
            // 2.1.1.1 數(shù)組擴容
            grow(minCapacity);
        }
    }
// 2.1.1.1 數(shù)組擴容
    private void grow(int minCapacity) {
        // overflow-conscious code
        // 獲取到 數(shù)組原長度
        int oldCapacity = elementData.length;
        // 獲取到新的數(shù)組長度 (新長度 = 原長度+ 0.5*原長度) >>1 右移一位相當(dāng)于除2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果新長度 小于 數(shù)組應(yīng)有的最小長度 的話 新長度就等于 最小長度
        // 這里 解決了 初始容量為1的arraylist 的擴容問題
        // 如果沒有這個判斷的話 根據(jù)上面的計算 1的擴容 newCapacity= 1+(1>>1) = 1 導(dǎo)致無法擴容
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 如果新長度 大于MAX_ARRAY_SIZE, MAX_ARRAY_SIZE這個
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            // 如果是 已經(jīng)大于了MAX_ARRAY_SIZE 就賦予一個很大的值 這個條件下 會賦值Integer的最大值
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 這里使用了 數(shù)組copy的api 來擴容數(shù)組
        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;
    }

3.1、 ArrayList內(nèi)置數(shù)組的擴容規(guī)則是什么椿每?

// 獲取到 數(shù)組原長度
int oldCapacity = elementData.length;
// 獲取到新的數(shù)組長度 (新長度 = 原長度+ 0.5*原長度) >>1 右移一位相當(dāng)于除2
int newCapacity = oldCapacity + (oldCapacity >> 1);

3.2、為什么ArrayList的默認長度是10汁尺?

從這可以看出 我們初始化時的長度是2多律,當(dāng)添加第三個元素的時候要擴容 2+(2>>1) = 3
如果 我們在添加第四個元素的話 會再次擴容 3+(3>>1) = 5 這樣的話,當(dāng)我們添加第六個元素的時候又會擴容。
從這里可以看出如果初始定義的長度比較小會造成頻繁擴容收毫。
所以 jdk默認的長度是10.

3.3此再、如果ArrayList初始化長度是1 那擴容的時候會怎么處理输拇?

具體看grow(int minCapacity)方法的實現(xiàn)策吠。
minCapacity = 2;
oldCapacity = 1; newCapacity = 1+(1>>1) ;
newCapacity = 1;
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
所以 這時候 newCapacity = 2;
最終擴容的結(jié)果是2;

4猴抹、get方法實現(xiàn)

get方法的實現(xiàn)比較簡單
1.檢查數(shù)組越界
2.返回對應(yīng)index的對象

// 3. get方法
    public Object get(int index){
        // 3.1 檢查是否越界
        rangeCheck(index);
        // 返回存儲對應(yīng)index的值
        return elementData[index];
    }
// 3.1 檢查是否越界
    private void rangeCheck(int index) {
        if (index >= size)
            // 3.1.1 輸出越界情況
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
// 3.1.1 輸出越界情況
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

5、remove(int index)移除元素方法實現(xiàn)

根據(jù)JDK中ArrayList的remove實現(xiàn) 可以得到remove的處理原理
刪除的原理
假設(shè) ArrayList中存放 1 2 3 4 5 6
現(xiàn)在remove(2)
所以可以獲取到要刪除 元素 是 3
3后面有 3個元素 4 5 6 的下標(biāo) 前移一位 覆蓋掉原來的3(這一步通過數(shù)組copy的方法來處理System.arraycopy)
結(jié)果就是 1 2 4 5 6
具體實現(xiàn)代碼

    public Object remove(int index) {
        // 4.1 檢查左邊是否越界
        rangeCheck(index);

        // 4.2 獲取到原來的元素
        Object oldValue = elementData[index];
        // 4.3 計算inedx后面 需要移動的元素的數(shù)量
        /*
        假設(shè) 1 2 3 4 5 6
        remove(2)
        numMoved = 6(size) - 2(index) - 1 = 3 所以后面三個元素要往前移動一個下標(biāo)
         */
        // 需要移動的元素的數(shù)量
        int numMoved = size - index - 1;

        // 如果后面沒有要移動的元素 就不做數(shù)組copy操作了
        if (numMoved > 0)
            // 4.4 處理數(shù)組 原數(shù)組是 elementData 從index+1開始復(fù)制 復(fù)制到 elementData 從index開始復(fù)制numMoved個元素
            // 通過這個方式 就把 elementData 的index元素用后面的元素覆蓋掉了
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        // 4.5 最后 size - 1 并把size-1后指向的最后一個元素置空
        elementData[--size] = null; // clear to let GC do its work
        // 4.6 返回被刪除的元素
        return oldValue;
    }

    //4.1 檢查是否越界
    private void rangeCheck(int index) {
        if (index >= size)
            // 3.1.1 輸出越界情況
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

6锁荔、remove(Object o)方法的實現(xiàn)

根據(jù)JDK中ArrayList相關(guān)方法的實現(xiàn)蟀给,我們可以看出這個方法的實現(xiàn)是基于remove(int index) 的。

判斷參數(shù)o是不是null

  1. 如果是null 阳堕,從index=0 開始遍歷elementDate內(nèi)置數(shù)組 找到null對應(yīng)的index跋理,通過index來移除null
  2. 如果不是null,從index=0 開始遍歷elementDate內(nèi)置數(shù)組 找到o對應(yīng)的index恬总,通過index來移除null
    public boolean remove(Object o) {
        // 5.1 判斷o是不是null
        if (o == null) {
            // 5.2如果是空的話 就會遍歷刪除 《《第一個》》 null 對象
            for (int index = 0; index < size; index++)
                // 判斷 index 對應(yīng)的元素是不是null
                if (elementData[index] == null) {
                    // 5.3 快速刪除index對應(yīng)的對象
                    fastRemove(index);
                    return true;
                }
        } else {
            // 5.4 如果不是空
            for (int index = 0; index < size; index++)
                // 5.5 遍歷數(shù)組
                if (o.equals(elementData[index])) {
                    //5.6 如果找到第一個equals的對象 就快速刪除掉
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    // 5.3/5.6 如果找到第一個equals的對象 就快速刪除掉
    // 與remove(index) 方法不同的地方是:1.不做越界檢查 2.不會返后被刪除的數(shù)據(jù)
    private void fastRemove(int index) {
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        elementData[--size] = null;
    }

7、add(int index,Object ele) 方法的具體實現(xiàn)

通過arraylist 對該方法的具體實現(xiàn) 可以看到具體的步驟是

  1. 檢查越界
  2. 確定內(nèi)置數(shù)組容量(包含擴容機制)
  3. 利用System.arraycopy方法壹堰,移動數(shù)組元素
  4. 賦值新對象到 內(nèi)置數(shù)組的指定的index上
  5. ArrayList的size+1

具體代碼實現(xiàn)

    // 6. 向指定的index 添加元素
    public void add(int index, Object ele) {
        // 6.1 檢查是否越界
        rangeCheckForAdd(index);

        // 6.2 確定是否需要擴容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 6.3 復(fù)制移動數(shù)組
        /*
           已有數(shù)組 A B C D
           向 index  1 插入 M
           通過arraycopy方法 elementData從index的位置開始復(fù)制 復(fù)制到 elementData的index+1的位置 復(fù)制的長度是 4 - 1 = 3
           所以移動完之后就是 A null B C D
         */
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        // 6.4 賦值對象到指定的index上
        elementData[index] = ele;
        // 6.5 元素總數(shù)量+1 size+1
        size++;
    }

 // 6.1 檢查是否越界
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    

8拭卿、全部代碼實現(xiàn)(詳細注釋)

package com.lhit.collection;

import java.util.Arrays;

public class MyArrayList {

    // 內(nèi)部數(shù)組
    private Object[] elementData;

    // 默認數(shù)組容量
    private static final int DEFAULT_CAPACITY = 10;

    // 用于空實例的共享空數(shù)組實例
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 共享空數(shù)組實例,用于默認大小的空實例缀旁。我們將其與EMPTY_ELEMENTDATA區(qū)分開來记劈,以了解添加第一個元素時應(yīng)該膨脹多少。
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    //ArrayList的大小(它包含的元素的數(shù)量)并巍。
    private int size;

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    // 1. 構(gòu)造方法 初始化內(nèi)部數(shù)組
    public MyArrayList(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);
        }
    }

    // 1. 構(gòu)造方法 初始化內(nèi)部數(shù)組
    public MyArrayList(){
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // 2. add方法
    public Boolean add(Object ele){

        // 2.1確定內(nèi)部數(shù)組的容量大小 判斷是否需要擴容(如果是默認無參數(shù)構(gòu)造方法生成的對象目木,在第一次add的時候會初始化內(nèi)部數(shù)組)
        ensureCapacityInternal(size + 1); // 這里傳入的參數(shù)是這個數(shù)字應(yīng)該有的最小值

        // 保存元素到數(shù)組中
        elementData[size++] = ele;

        return true;
    }

    // 3. get方法
    public Object get(int index){
        // 3.1 檢查是否越界
        rangeCheck(index);
        // 返回存儲對應(yīng)index的值
        return elementData[index];
    }

    // 4. remove 通過index
    /*
        刪除的原理
        假設(shè) ArrayList中存放 1 2 3 4 5 6
        現(xiàn)在remove(2)
        所以可以獲取到 元素 是 3
        3后面有 3個元素 4 5 6 的下標(biāo) 前移 覆蓋掉原來的3(這一步通過數(shù)組copy的方法來處理System.arraycopy)
        結(jié)果就是 1 2 4 5 6
     */
    public Object remove(int index) {
        // 4.1 檢查左邊是否越界
        rangeCheck(index);

        // 4.2 獲取到原來的元素
        Object oldValue = elementData[index];
        // 4.3 計算inedx后面 需要移動的元素的數(shù)量
        /*
        假設(shè) 1 2 3 4 5 6
        remove(2)
        numMoved = 6(size) - 2(index) - 1 = 3 所以后面三個元素要往前移動一個下標(biāo)
         */
        // 需要移動的元素的數(shù)量
        int numMoved = size - index - 1;

        // 如果后面沒有要移動的元素 就不做數(shù)組copy操作了
        if (numMoved > 0)
            // 4.4 處理數(shù)組 原數(shù)組是 elementData 從index+1開始復(fù)制 復(fù)制到 elementData 從index開始復(fù)制numMoved個元素
            // 通過這個方式 就把 elementData 的index元素用后面的元素覆蓋掉了
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        // 4.5 最后 size - 1 并把size-1后指向的最后一個元素置空
        elementData[--size] = null; // clear to let GC do its work
        // 4.6 返回被刪除的元素
        return oldValue;
    }

    // 5. remove 通過Object元素來刪除
    // 需要注意的是 如果存在相同對象 只能刪除index靠前的第一個
    public boolean remove(Object o) {
        // 5.1 判斷o是不是null
        if (o == null) {
            // 5.2如果是空的話 就會遍歷刪除 《《第一個》》 null 對象
            for (int index = 0; index < size; index++)
                // 判斷 index 對應(yīng)的元素是不是null
                if (elementData[index] == null) {
                    // 5.3 快速刪除index對應(yīng)的對象
                    fastRemove(index);
                    return true;
                }
        } else {
            // 5.4 如果不是空
            for (int index = 0; index < size; index++)
                // 5.5 遍歷數(shù)組
                if (o.equals(elementData[index])) {
                    //5.6 如果找到第一個equals的對象 就快速刪除掉
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }


    // 6. 向指定的index 添加元素
    public void add(int index, Object ele) {
        // 6.1 檢查是否越界
        rangeCheckForAdd(index);

        // 6.2 確定是否需要擴容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 6.3 復(fù)制移動數(shù)組
        /*
           已有數(shù)組 A B C D
           向 index  1 插入 M
           通過arraycopy方法 elementData從index的位置開始復(fù)制 復(fù)制到 elementData的index+1的位置 復(fù)制的長度是 4 - 1 = 3
           所以移動完之后就是 A null B C D
         */
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        // 6.4 賦值對象到指定的index上
        elementData[index] = ele;
        // 6.5 元素總數(shù)量+1 size+1
        size++;
    }

    // 2.1/6.2 確定數(shù)組的長度
    private void ensureCapacityInternal(int minCapacity) {
        // 判斷是否是使用默認無參數(shù)構(gòu)造方法來創(chuàng)建的arraylist
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 如果是的話 對比需要的最小數(shù)組長度和默認數(shù)組長度 獲取到其中的最大值 作為內(nèi)部數(shù)組的最小長度
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // 2.1.1明確數(shù)組長度
        ensureExplicitCapacity(minCapacity);
    }

    // 2.1.1明確數(shù)組長度 參數(shù)是數(shù)組應(yīng)有的最小容量長度
    private void ensureExplicitCapacity(int minCapacity) {

        // overflow-conscious code
        // 如果數(shù)組需要的最小值 大于當(dāng)前數(shù)組的長度 則數(shù)組需要擴容
        if (minCapacity - elementData.length > 0){
            // 2.1.1.1 數(shù)組擴容
            grow(minCapacity);
        }
    }

    // 2.1.1.1 數(shù)組擴容
    private void grow(int minCapacity) {
        // overflow-conscious code
        // 獲取到 數(shù)組原長度
        int oldCapacity = elementData.length;
        // 獲取到新的數(shù)組長度 (新長度 = 原長度+ 0.5*原長度) >>1 右移一位相當(dāng)于除2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果新長度 小于 數(shù)組應(yīng)有的最小長度 的話 新長度就等于 最小長度
        // 這里 解決了 初始容量為1的arraylist 的擴容問題
        // 如果沒有這個判斷的話 根據(jù)上面的計算 1的擴容 newCapacity= 1+(1>>1) = 1 導(dǎo)致無法擴容
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 如果新長度 大于MAX_ARRAY_SIZE, MAX_ARRAY_SIZE這個
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            // 如果是 已經(jīng)大于了MAX_ARRAY_SIZE 就賦予一個很大的值 這個條件下 會賦值Integer的最大值
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 這里使用了 數(shù)組copy的api 來擴容數(shù)組
        elementData = Arrays.copyOf(elementData, newCapacity);

        // 從這可以看出 我們初始化時的長度是2,當(dāng)添加第三個元素的時候要擴容 2+(2>>1) = 3
        // 如果 我們在添加第四個元素的話 會再次擴容 3+(3>>1) = 5 這樣的話刽射,當(dāng)我們添加第六個元素的時候又會擴容军拟。
        // 從這里可以看出如果初始定義的長度比較小會造成頻繁擴容。所以 jdk默認的長度是10.

        // 這里如果初始化長度是1 那擴容的時候會怎么處理誓禁?
        // 具體看grow(int minCapacity)方法的實現(xiàn)懈息。
        /*
        minCapacity = 2;
        oldCapacity = 1; newCapacity = 1+(1>>1) ;
        newCapacity = 1;
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        所以 這時候 newCapacity = 2;
        最終擴容的結(jié)果是2;
        */
    }

    // 3.1/4.1 檢查是否越界
    private void rangeCheck(int index) {
        if (index >= size)
            // 3.1.1 輸出越界情況
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    // 3.1.1 輸出越界情況
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    // 5.3/5.6 如果找到第一個equals的對象 就快速刪除掉
    // 與remove(index) 方法不同的地方是:1.不做越界檢查 2.不會返后被刪除的數(shù)據(jù)
    private void fastRemove(int index) {

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        elementData[--size] = null;
    }

    // 6.1 檢查是否越界
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }


    // 獲取一個極大的長度
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }

    // 獲取當(dāng)前ArrayList的元素數(shù)量
    public int getSize() {
        return size;
    }
}

9、Vector的擴容機制

這里吧jdk中的Vector中的擴容函數(shù)拿過來了

    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }
   
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
    
    public Vector() {
        this(10);
    }

capacityIncrement 參數(shù)是Vector初始化時可以指定的 默認是0

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 這是是與ArrayList擴容最大的不同點
        // Vector 當(dāng)默認是0的情況下 會 是2倍擴容
        // 如果初始化時指定了每次擴容的增長容量 則會按照增長量擴容
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

9.1 Vector與ArrayList有什么不同?

  1. Vector 源碼中使用synchronized關(guān)鍵字較多摹恰,線程安全要好于ArrayList辫继。
  2. Vector與ArrayList的內(nèi)置數(shù)組的擴容機制不同。默認情況下Vector是兩倍擴容俗慈,ArrayList是1.5倍擴容

9.2 Vector的擴容機制是什么樣的?

Vector在默認情況下是2倍擴容姑宽,如果在初始化時指定的每次擴容的容量,則會按照指定容量大小擴容闺阱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炮车,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子酣溃,更是在濱河造成了極大的恐慌瘦穆,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赊豌,死亡現(xiàn)場離奇詭異扛或,居然都是意外死亡,警方通過查閱死者的電腦和手機亿絮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門告喊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人派昧,你說我怎么就攤上這事÷G校” “怎么了蒂萎?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長淮椰。 經(jīng)常有香客問我五慈,道長,這世上最難降的妖魔是什么主穗? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任泻拦,我火速辦了婚禮,結(jié)果婚禮上忽媒,老公的妹妹穿的比我還像新娘争拐。我一直安慰自己,他們只是感情好晦雨,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布架曹。 她就那樣靜靜地躺著隘冲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绑雄。 梳的紋絲不亂的頭發(fā)上展辞,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音万牺,去河邊找鬼罗珍。 笑死,一個胖子當(dāng)著我的面吹牛脚粟,可吹牛的內(nèi)容都是我干的覆旱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼珊楼,長吁一口氣:“原來是場噩夢啊……” “哼通殃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厕宗,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤画舌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后已慢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體曲聂,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年佑惠,在試婚紗的時候發(fā)現(xiàn)自己被綠了朋腋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡膜楷,死狀恐怖旭咽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赌厅,我是刑警寧澤穷绵,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站特愿,受9級特大地震影響仲墨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜揍障,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一目养、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毒嫡,春花似錦癌蚁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽礼旅。三九已至,卻和暖如春洽洁,著一層夾襖步出監(jiān)牢的瞬間痘系,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工饿自, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留汰翠,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓昭雌,卻偏偏與公主長得像复唤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子烛卧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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