zoukankan      html  css  js  c++  java
  • 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()]);



    总结




  • 相关阅读:
    poj 3666 Making the Grade
    poj 3186 Treats for the Cows (区间dp)
    hdu 1074 Doing Homework(状压)
    CodeForces 489C Given Length and Sum of Digits...
    CodeForces 163A Substring and Subsequence
    CodeForces 366C Dima and Salad
    CodeForces 180C Letter
    CodeForces
    hdu 2859 Phalanx
    socket接收大数据流
  • 原文地址:https://www.cnblogs.com/erinchen/p/11641959.html
Copyright © 2011-2022 走看看