集合-ArrayList

对于调试jdk源码,若是发现无法在调试过程中查看源码中的变量,可以参考这篇文章:https://blog.csdn.net/u010407050/article/details/76690478

参考:http://www.cnblogs.com/skywang12345/p/3323085.html

removeIf() 方法 https://blog.csdn.net/qq_27093465/article/details/79154566

在接口collection里面的一个默认方法,当继承collection后,如果不自己实现这个方法就会采用这个默认的方法。

java.util.ArrayList.removeIf   ArrayList类重写了这个方法
  @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
        int removeCount = 0; //记录删除元素的个数
        final BitSet removeSet = new BitSet(size);  //记录被删除的元素的索引 在需要删除的元素那个索引那置为true
        final int expectedModCount = modCount;   //在未做处理前被更改的次数
        final int size = this.size;  //集合包含元素的个数
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {  //按照过滤器来确定删除哪些元素,以及这些元素的索引
                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++) { 将那些标志位false的元素往左移,填补那些需要删除的元素的位置
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) { 将新的集合的新长度之后的元素都置为null,便于gc进行垃圾回收
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++; 
        }
        return anyToRemove;
    }

参考:http://www.cnblogs.com/skywang12345/p/3308556.html

          http://www.cnblogs.com/zhangyinhua/p/7687377.html

ArrayList

//void java.util.ArrayList.trimToSize()
    /**
     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
     * list's current size.  An application can use this operation to minimize
     * the storage of an <tt>ArrayList</tt> instance.
     */
    public void trimToSize() { 将ArrayList的容量减至最低,与元素的个数相同 这样可以节约存储空间
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size); 只取这个数组只的size大小的元素的数组
        }
    }
//void java.util.ArrayList.ensureCapacity(int minCapacity)
    /**
     * Increases the capacity of this <tt>ArrayList</tt> instance, if
     * necessary, to ensure that it can hold at least the number of elements
     * specified by the minimum capacity argument.
     *
     * @param   minCapacity   the desired minimum capacity
     */
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table 如果是已经插入过值的ArrayList,那么最小扩容是任意,
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0) 只有现在设置的容量比之前的数组容量大才需要扩容
            grow(minCapacity);
    }
    /**
     * 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); 原来容量的1.5倍
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity; 若是现在这个容量比你设置的那个容量要小的话,就采用你设置的那个容量,不然就设置为原来容量的1.5倍
        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);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    public int indexOf(Object o) { 查找出元素在ArrayList中出现的第一次的位置  顺序遍历
        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;
    }

    public int lastIndexOf(Object o) { 查找出元素在ArrayList中出现的最后一次,沿着数组反向遍历即可
        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;
    }
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)  如果a的长度比原ArrayList的长度要小  这个a数组就放不下原ArrayList转成成的数组
            // Make a new array of a's runtime type, but my contents:生成一个新的数组,将原来的ArrayList中的元素拷贝进去,返回
            return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 
        System.arraycopy(elementData, 0, a, 0, size); 将ArrayList中的元素拷贝到a数组中,覆盖原有值
        if (a.length > size) 将a数组后面多的元素清空
            a[size] = null;
        return a;
    }
    public E remove(int index) {
        rangeCheck(index); 
        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1; 在删除元素后,需要移动的数量
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved); 在删除index处的数据后,将所有的index后面的元素向前移动
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
    public boolean remove(Object o) {  删除指定元素
        if (o == null) {  如果是null的话,就把数组中所有的null给删除
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    private void fastRemove(int index) { 快速删除索引为index的元素,因为这里快速就是没经过检查index是否超出范围
        modCount++;                      这个方法是一个私有方法,只在类的内部调用
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }
    /**
     * 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;
    }clear操作只是将数组中所有元素置为null,然后将数组的大小(元素的个数)设置为0
    public boolean addAll(int index, Collection<? extends E> c) { 将一个集合插入到index处
        rangeCheckForAdd(index);
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)  先将index后面的数据整体往后移动numNew个单位
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
        System.arraycopy(a, 0, elementData, index, numNew); 将数据拷贝进来
        size += numNew;
        return numNew != 0;
    }

 

 

posted @ 2019-01-16 19:21  弱水三千12138  阅读(235)  评论(0编辑  收藏  举报