JDK1.8集合-ArrayList


繼承關系
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

常量
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * Default initial capacity.
     * 默認初始化容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     * 空數組共享實例
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     * 缺省大小的空數組共享實例
     * 與EMPTY_ELEMENTDATA區分開,以便知道第一個元素添加時如何擴容
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     * 最大可分配大小
    存內存存儲對象頭信息和對象頭信息 8個字節
2<sup>31</sup>-1 0111后面28個1,也就是一共31個1的整數,2^31 - 1
*/ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

成員變量
    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access 非私有,以簡化嵌套類的訪問
當對象存儲時,它的值不需要維持,敏感信息例如密碼,用transient關鍵字標記的成員變量不參與序列化過程
/** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;


構造函數
  /**
     * Constructs an empty list with the specified initial capacity.
     * 根據給定初始容量構造一個空的list
     *
     * @param initialCapacity the initial capacity of the list
     *                        list初始容量
     * @throws IllegalArgumentException if the specified initial capacity
     *                                  is negative
     *                                  當給定的初始容量非負時拋出異常
     */
    public ArrayList(int initialCapacity) {
//        判斷給定初始化容量是否合法
        if (initialCapacity > 0) {
//            創建數組
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
//            指向EMPTY_ELEMENTDATA
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
//    ?是“任意類”  E是指定類型 
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {//elementData 非空時候
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
//            c.toArray不返回 Object[]的時候,則進行數組拷貝 這邊不理解
//當elementData不是Object數組時,它會使用Arrays.copyOf()方法構造一個Object數組替換elementData
if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }

函數

增加
  尾部增加元素
  指定位置添加元素
  尾部增加集合
  指定位置添加集合
 
        
/**
     * Appends the specified element to the end of this list.
     *
     * @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!!
        // 尾部放入元素 容量+1
        elementData[size++] = e;
        return true;
    }


private static int calculateCapacity(Object[] elementData, int minCapacity) {
無參數初始化ArrayList時,每次插入元素,都需要 取 10和容量的 最大值嗎?DEFAULTCAPACITY_EMPTY_ELEMENTDATA初始為空數組,之后增加元素,但地址仍不變,所以 仍 == ?
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private void ensureExplicitCapacity(int minCapacity) { //操作計算+1 modCount++; // overflow-conscious code // 只有當容量不夠時才擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); } /** * The maximum size of array to allocate. * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit * 最大可分配大小 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * 緩沖數組擴容以確保能夠存儲給定元素 * @param minCapacity the desired minimum capacity * 期望的最小容量 */ 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: // 最小擴容容量通常接近size 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; }
     /**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     * 指定位置添加元素
     * @param index   index at which the specified element is to be inserted
     * @param element element to be inserted
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        //判斷邊界,可能會發生數組越界
        rangeCheckForAdd(index);
        //確保內部容量
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //調用效率較高的System.arraycopy進行數組復制
        //目的為空出指定位置
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        //指定位置上放入指定元素
        elementData[index] = element;
        //容量+1
        size++;
    }
    /**
     * A version of rangeCheck used by add and addAll.
     */
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

 

     增加 集合
     /**
     * Appends all of the elements in the specified collection to the end of
     * this list, in the order that they are returned by the
     * specified collection's Iterator.  The behavior of this operation is
     * undefined if the specified collection is modified while the operation
     * is in progress.  (This implies that the behavior of this call is
     * undefined if the specified collection is this list, and this
     * list is nonempty.)
     *
     * @param c collection containing elements to be added to this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * Inserts all of the elements in the specified collection into this
     * list, starting at the specified position.  Shifts the element
     * currently at that position (if any) and any subsequent elements to
     * the right (increases their indices).  The new elements will appear
     * in the list in the order that they are returned by the
     * specified collection's iterator.
     *
     * @param index index at which to insert the first element from the
     *              specified collection
     * @param c     collection containing elements to be added to this list
     * @return <tt>true</tt> if this list changed as a result of the call
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws NullPointerException      if the specified collection is null
     */
    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)
            System.arraycopy(elementData, index, elementData, index + numNew,
                    numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

  

set 修改
        /**
     * Replaces the element at the specified position in this list with
     * the specified element.
     *
     * @param index   index of the element to replace
     * @param element element to be stored at the specified position
     * @return the element previously at the specified position
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        // 范圍檢查
        rangeCheck(index);
        // 取出舊值用以返回
        E oldValue = elementData(index);
        // 放入新的值
        elementData[index] = element;
        return oldValue;
    }



    /**
     * Checks if the given index is in range.  If not, throws an appropriate
     * runtime exception.  This method does *not* check if the index is * negative: It is always used immediately prior to an array access,沒看明白為什么不檢查負數
     * which throws an ArrayIndexOutOfBoundsException if index is negative.
     */
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

 

 

remove 刪除
    根據下標移除
    根據對象移除
    根據集合移除
    根據過濾器移除
    根據范圍移除(受保護的方法)   

 /**
     * 刪除指定位置的元素,后繼元素 左移
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     *
     * @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);
        // 操作計數 +1
        modCount++;
        //獲取指定位置的元素,用於返回
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        // index 位置后面的元素 System.arraycopy的方式 前移
        if (numMoved > 0)
            System.arraycopy(elementData, index + 1, elementData, index,
                    numMoved);
        // 最后一個數組元素引用置null  方便GC
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

    /**
     * 當元素存在的時候,刪除第一個找到的指定的元素
     * 如果元素不存在,則list不會變動
     * Removes the first occurrence of the specified element from this list,
     * if it is present.  If the list does not contain the element, it is
     * unchanged.  More formally, removes the element with the lowest index
     * <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
     * (if such an element exists).  Returns <tt>true</tt> if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     *
     * @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) {
        // o 是否是null元素,數組允許存儲null
        if (o == null) {
            for (int index = 0; index < size; index++)
                // 用 == 比較  null
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                // 用  equals比較 非null
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    /**
     * // 根據給定的集合,將list中與集合相同的元素全部刪除
     * Removes from this list all of its elements that are contained in the
     * specified collection.
     *
     * @param c collection containing elements to be removed from this list
     * @return {@code true} if this list changed as a result of the call
     * @throws ClassCastException   if the class of an element of this list
     *                              is incompatible with the specified collection
     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this list contains a null element and the
     *                              specified collection does not permit null elements
     *                              (<a href="Collection.html#optional-restrictions">optional</a>),
     *                              or if the specified collection is null
     * @see Collection#contains(Object)
*/ public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); //判斷非空,空拋出異常 return batchRemove(c, false); } /** * 通過一個過濾器接口實現,來實現刪除 * @param filter * @return */ @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); // figure out which elements are to be removed // any exception thrown from the filter predicate at this stage // will leave the collection unmodified // 用bitset來存儲哪些下標對應的元素要刪除,哪些下標對應的元素要保存 // Bitset中主要存儲的是二進制位,做的也都是位運算,每一位只用來存儲0,1值,主要用於對數據的標記。 int removeCount = 0; final BitSet removeSet = new BitSet(size); // 判斷並發修改用 final int expectedModCount = modCount; final int size = this.size; // 按順序遍歷且沒有並發修改 for (int i = 0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") //告訴編譯器忽略 unchecked 警告信息,如使用List,ArrayList等未進行參數化產生的警告信息。

final E element = (E) elementData[i];
//利用過濾器匹配元素,如果匹配,則刪除計數+1,並將下標進行存儲
            if (filter.test(element)) {//Predicate是個斷言式接口 and,or和negate &&、||和! isEqual removeSet.set(i); removeCount++; } } // 判斷是否存在並發修改
        if (modCount != expectedModCount) { // 拋出並發修改異常
            throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements // 判斷是否有要刪除的元素
        final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; for (int i = 0, j = 0; (i < size) && (j < newSize); i++, j++) { // 下一個要保存的元素
                i = removeSet.nextClearBit(i); // 存放到新數組
                elementData[j] = elementData[i]; } // 把實際要保存的元素之后的全部 置為 null ,用以GC // 實際上,上面的操作已經將要保留的元素全部前移了,后面的元素都是不保留的,所以要置為null來幫助GC
            for (int k = newSize; k < size; k++) { elementData[k] = null;  // Let gc do its work
 } //設置size
            this.size = newSize; // 判斷是否並發修改
            if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; } /** * 刪除指定范圍的元素 * Removes from this list all of the elements whose index is between * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. * Shifts any succeeding elements to the left (reduces their index). * This call shortens the list by {@code (toIndex - fromIndex)} elements. * (If {@code toIndex==fromIndex}, this operation has no effect.) * * @throws IndexOutOfBoundsException if {@code fromIndex} or * {@code toIndex} is out of range * ({@code fromIndex < 0 || * fromIndex >= size() || * toIndex > size() || * toIndex < fromIndex}) */
    protected void removeRange(int fromIndex, int toIndex) { modCount++; // 1保留 - 2刪除 - 3保留 將3copy到1后面,多余部分置空,幫助GC
        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; } /** * 批量刪除 * @param c * @param complement * @return
     */
    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++) // complement // removeAll 為false ,下標r的元素不在刪除集合c中,存儲的是 不刪除的元素 // retainAll 為true ,下標r的元素在刪除集合c中,存儲的是 刪除的元素 
                if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. // 這里判斷循環是否正常
            if (r != size) { // 如果不正常的話,需要挪動元素
 System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } // 如果需要刪除元素的話,則證明一部分位置需要置null,幫助GC,設置修改GC
            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; }

 

get 獲取
    /**
     * Returns the element at the specified position in this list.
     *
     * @param index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }
contains
  public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    /**
     * 首次出現下標
     * 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 <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     */
    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;
    }

    /**
     * Returns the index of the last occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the highest index <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     */
    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;
    }

 

clear

    /**
     * Removes all of the elements from this list.  The list will
     * 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;
    }

 

public Object[] toArray()和public T[] toArray(T[] a)
 
以后再看

    List<Integer> list = new ArrayList<>();
    Collections.addAll(list,1,2,3,4,5,6);
    // 方式1 //
    list.toArray(new Integer[0]); //涉及到反射,效率較低
    // 方式2 //
    list.toArray(new Integer[list.size()]);

 




總結





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM