• 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()]);



    总结




  • 相关阅读:
    .net实现浏览器大文件分片上传
    asp.net实现浏览器大文件分片上传
    php实现浏览器大文件分片上传
    Java实现浏览器大文件分片上传
    文件分片上传
    大文件分片上传
    pdf缩略图生成上传解决方案
    专业精神的三个步骤
    安卓TabHost+ViewPager+RadioGroup多功能模板整理
    java基础之概谈xml文件解析
  • 原文地址:https://www.cnblogs.com/erinchen/p/11641959.html
Copyright © 2020-2023  润新知