ArrayList Source Code

ArrayList Source Code

說明

承了RanddomAccess —->遍歷的話用for最好

elementData是數組 所以在順序插入和隨機訪問的情況下使用這個最好

list可以放入重複的值

構造方法

​ 先將繼承集合接口Collection的C(如hashset)轉化爲數組 如果數組長度不是0 而且對象不是Object[] (elementData類型)則將轉成Object[]

 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;
        }
    }

方法

trimToSize()

public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

說明:

Trims the capacity of this ArrayList instance to be the list’s current size. An application can use this operation to minimize the storage of an ArrayList instance.

將ArrayList實例的容量 變爲list的當前大小 . 應用可以使用這個操作最小化ArrayList實例的存儲

獲取ArrayList的元素個數是用size. 而length是ArrayList申請的容量大小. 便於不用每次增加的時候都去進行擴容操作.在isEmpty()方法裏判斷是否爲null的時候 直接用size==0判斷

modCount是什麼? The number of times this list has been structurally modified

這個字段主要防止多線程操作的情況下 ArrayList發生結構性的變化. 例如一個線程正在遍歷 而另一個線程正在remove. 在遍歷的過程中 會發現某個元素爲null 這時 modCount 會告訴迭代器 讓其拋出ConcurrentModificationException.如果沒有這一個變量,那麼系統肯定會報異常ArrayIndexOutOfBoundsException,這樣的異常顯然不是應該出現的(這些運行時錯誤都是使用者的邏輯錯誤導致的,我們的JDK那麼高端,不會出現使用錯誤,我們只拋出使用者造成的錯誤,而這個錯誤是設計者應該考慮的),爲了避免出現這樣的異常,定義了檢查。—從這裏也可以看出 ArrayList是非線程安全的

參考知乎:https://www.zhihu.com/question/24086463/answer/64717159

add()

說明:Appends the specified element to the end of this list 添加指定元素到list尾部

 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

在 空參初始化的時候 elementData=DFAULTCAPACITY_EMPTY_ELEMENTDATA 然後返回最小容量是默認容量 10 還是size+1 .然後確定明確的容量ensureExplicitCapacity 如果大於10 則擴容 grow

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
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);
    }

如何擴容?

看到第二行 就知道 容量變成原來的1.5倍 然後copy到新的數組

更詳細的參考:https://blog.csdn.net/wangb_java/article/details/79515302

remove(int index)

說明 Removes the element at the specified position in this list Shifts any subsequent elements to the left 移除list指定位置的元素 將之後的所有元素向左轉移

 public E remove(int index) {
        rangeCheck(index);//判斷是否越界
        modCount++;
        E oldValue = elementData(index);
        int numMoved = size - index - 1;//獲取index位置開始到最後一個位置的個數
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved); // 將elementData數組index+1位置開始拷貝到elementData從index開始的空間
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

batchRemove(Collection

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];// 直接將r位置的元素賦值給w位置的元素,w自增  
        } finally {
            //保留與AbstractCollection的行爲兼容性 防止拋出異常導致上面r的右移過程沒完成 
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            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;
    }

int indexOf(Object o)

說明:Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
大體意識是 找到指定元素o在list第一次出現的位置. 如果 list中沒有o則返回-1.

 public int indexOf(Object o) {
        if (o == null) {//元素o 爲null 則得到該數組中第一個元素爲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;
    }

Object clone()

說明:Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
返回ArrayList實例的淺複製 元素本身不被複制

public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            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(e);
        }
    }

這個 淺複製深複製 的區別 參考:https://blog.csdn.net/accp_fangjian/article/details/2423252

toString()

說明:這個方法是繼承父類AbstractCollection的Object的 toString()方法.
一般 對數組toString()輸出的的值沒有太大的意義.但是集合的toString()是打印出集合中的內容,就是因爲 AbstractCollection

public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();//在不考慮 線程安全的情況下 字符串拼接最好用StringBuilder
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章