【JDK1.8集合】之ArrayList

ArrayList的特点有:存取有序,元素可以重复,可以存null值,因为底层是数组,所以查询快,增删相对慢,非线程安全。

先看成员属性:

 //默认初始容量
 private static final int DEFAULT_CAPACITY = 10;

 //被用于空实例的共享空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

 //存放元素的数组,数组的长度为List的size
//当元素被添加的时候,List的容量会被扩充到 DEFAULT_CAPACITY(10)
// 非private是为了方便嵌套类的访问
//transient 修饰,该属性不会序列化,ArrayList有自己的序列化方法
 transient Object[] elementData;

//size,List的大小
private int size;

构造函数:

//无参构造,对容器进行初始化赋值{}。
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

//自定义容量的构造函数,必须大于等于0。
    public ArrayList(int initialCapacity) {
        //如果大于0
        if (initialCapacity > 0) {
            //对存元素的数组进行初始化
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            //和无参构造一样,将存放元素的数组进行默认初始化{}
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            //小于0,抛异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                    initialCapacity);
        }
    }

//集合构造函数
    public ArrayList(Collection<? extends E> c) {
        //将集合转换为数组,并赋值给元素容器
        elementData = c.toArray();

        if ((size = elementData.length) != 0) {
            // 如果不是空集合,检查是否成功转换为数组
            if (elementData.getClass() != Object[].class)
                //如果转换不成功,直接copy
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // 空集合,
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

 

添加指定元素:

//将元素添加到该List的末尾.
    public boolean add(E e) {
        //size为当前List大小
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

  private void ensureCapacityInternal(int minCapacity) {
        //如果是第一次添加元素
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //在DEFAULT_CAPACITY(10)和当前的size+1取一个最大值
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

  private void ensureExplicitCapacity(int minCapacity) {
        //记录结构性修改次数
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

//增加数组的容量,确保它至少能容纳指定的最小容量的元素量。
    //minCapacity 期望的最小容量
    private void grow(int minCapacity) {
        // overflow-conscious code
        //记录当前容量大小
        int oldCapacity = elementData.length;
        //新容量为旧容量的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //保证新容量最小为当前容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //保证新容量不大于Integer.MAX_VALUE - 8
        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);
    }

指定位置添加:

//将元素插入到List的指定位置
 public void add(int index, E element) {
        //检查index,保证size>index>0。
        rangeCheckForAdd(index);
        //如果容量不足,将进行扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //将数组的元素从index开始后面的元素(size-index),统一后移一位。
        System.arraycopy(elementData, index, elementData, index + 1,
                size - index);
        elementData[index] = element;
        size++;
    }

private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

添加指定集合:

//将新Collection(按照迭代器所返回的元素顺序)的所有元素添加到该List的尾部.
//Collection为空将NullPointerException.
public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        //将a[0--(numNew-1)] copy 到 elementData[size--(size+numNew-1)]
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

//添加指定集合到指定位置。
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;
    }

 

删除指定元素:

// 删除List指定位置上的元素
    public E remove(int index) {
        //确保size>=index
        rangeCheck(index);
        //
        modCount++;
        //记录指定索引上的元素,作为返回值
        E oldValue = elementData(index);
        //计算出index后面元素前移一位的位置,准备copy
        int numMoved = size - index - 1;
        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中首次出现的指定元素(如果存在),
    //ArrayList可以存放重复元素。
    public boolean remove(Object o) {
        //如果元素为null
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        //不为null
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

 //删除指定位置元素,跳过index参数的边界检查以及不返回任何值
    private void fastRemove(int index) {
        modCount++;
        //计算出index后面元素前移一位的位置,准备copy
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        //将数组最后一个元素设置为null,由GC清理
        elementData[--size] = null; // clear to let GC do its work
    }

 

删除List中指定的集合:

//删除List中指定Collection(非空)里面的元素
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

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++)
                //判断容器中是否包含elementData[r]元素
                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;
            }
            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;
    }

 

删除指定边界的元素:

 //删除指定边界的元素,包小不包大。
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        //计算出index后面元素前移一位的位置,准备copy
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                numMoved);

        // GC处理
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

 

1.8新增的remove方法:

//刪除所有滿足指定条件的元素
    @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);
        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++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

ArrayList的get方法:

 //获得指定位置的元素index<=size
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

 

ArrayList的set方法:

//将指定位置的值替换为新值
    public E set(int index, E element) {
        //
        rangeCheck(index);
        //记录指定位置上的元素,作为返回值
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

 

查找元素方法:

//顺序查找,返回元素第一次出现的位置,如果元素不存在,则返回-1
    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;
    }

//逆序查找,返回元素最后一次出现的位置,如果元素不存在,则返回-1
    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;
    }

 

 

如果有不对的地方欢迎指出。

posted @ 2017-10-19 17:58  emoji的博客  阅读(562)  评论(0编辑  收藏  举报