[Source] ArrayList notes

ArrayList is an array of variable length, is commonly used in the actual development, after analysis by parsing the source and record your own understanding.


ArrayList allowed into null;

ArrayList threads are not synchronized;


Inheritance (achieve) the relationship

extends

|---AbstractList<E>

implements

|---List<E>
|---RandomAccess
|---Cloneable
|---java.io.Serializable


Field

   
    //序列化的版本号
    private static final long serialVersionUID = 8683452581122892189L;

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

    //以含参构造函数创建且指定长度为0时使用的数组实例
    private static final Object[] EMPTY_ELEMENTDATA = {};

    //以空参构造函数创建时使用的数组实例
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    //存放元素的数组的引用
    transient Object[] elementData;

    //实际存放元素的个数
    private int size;

Construction method

1. The no-argument constructor

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

Analysis: When creating ArrayList instance constructor with no arguments, the underlying array elementData reference point to a length of the array instance DEFAULTCAPACITY_EMPTY_ELEMENTDATA 0, the capacity is 0 at this time.

2. ① containing configuration parameters

    public ArrayList(int initialCapacity) {
        
        //如果指定的初始容量大于0,实例化一个长度为initialCapacity的数组,并赋值给elementData
        if (initialCapacity > 0) {

            this.elementData = new Object[initialCapacity];

        } else if (initialCapacity == 0) {

            /*  如果指定的初始化容量等于0,底层数组引用elementData会指向长度为0的数组实例
             *  EMPTY_ELEMENTDATA    
             */                 
            this.elementData = EMPTY_ELEMENTDATA;
        } else {

            //如果指定的初始化容量小于0,抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

Analysis: The constructor can specify the initial capacity, the incoming parameters initialCapacity is the initial capacity.

3. ② containing configuration parameters

    public ArrayList(Collection<? extends E> c) {
        
        //将集合c转化为数组,赋值给elementData
        elementData = c.toArray();

        //如果数组长度不等于0
        if ((size = elementData.length) != 0) {
            
            //如果得到的数组不是一个Object[]类型的数组,将其转化为Object[]
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        
        } 
        else {
            //如果数组长度为0,element指向EMPTY_ELEMENTDATA
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

Analysis: The constructor can be configured to specify a set of elements comprises a set.



Dynamic growth mechanism :( expansion process)

A method to add elements add (E e) an example of the analysis of the dynamic growth mechanism ArrayList

1. Call add (E e) a method of increasing an element.

2. internally add (E e) method calls ensureCapacityInternal method. Determining whether a set of configuration parameters is instantiated empty, and if so, the default initial capacity (DEFAULT_CAPACITY = 10) as the minimum length required; if not, the minimum capacity size + 1 places as required.

private void ensureCapacityInternal(int minCapacity) {

        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

3. Call ensureExplicitCapacity method within ensureCapacityInternal method. Determining a minimum required capacity exceeds the length of the current array.

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

        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

4. If the minimum required length of the current exceeds the capacity of the array, the method calls for expansion grow. Try 1.5 times the original volume as a new volume newCapacity, if the new capacity is less than a minimum capacity minCapacity newCapacity required, then the required minimum length as the new minCapacity capacity. It is then determined whether the new capacity is larger than MAX_ARRAY_SIZE (Integer.MAX_VALUE-8), if exceeded, will Integer.MAX_VALUE as a new capacity, otherwise MAX_ARRAY_SIZE (Integer.MAX_VALUE-8) as a new capacity, assigned to the original length of the array newCapacity new array, the array length at this time really changed, the expansion is complete.

private void grow(int minCapacity) {
        
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) 
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }


The main method

1.add (E e): add an element to the end of O (1)

    public boolean add(E e) {

        //判断是否扩容
        ensureCapacityInternal(size + 1);
        //将元素存放到末尾    
        elementData[size++] = e;
        return true;
    }

2.add (int index, E e): add an element to a specified position O (n)

    public void add(int index, E element) {

        //判断是否越界
        rangeCheckForAdd(index);

        //判断是否需要扩容
        ensureCapacityInternal(size + 1);  

        //将将index位置之后的元素后移
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);

        //将元素存放到index位置上
        elementData[index] = element;

        size++;
    }

3.addAll (Collection <? Extends E> c): a collection of elements added in order to end the iteration

    public boolean addAll(Collection<? extends E> c) {
        
        //将集合c转为数组a
        Object[] a = c.toArray();

        //记录数组长度numNew
        int numNew = a.length;

        //判断是否需要扩容
        ensureCapacityInternal(size + numNew); 
        
        //将数组a的复制到原数组或扩容后的数组中
        System.arraycopy(a, 0, elementData, size, numNew);

        //更新元素个数size
        size += numNew;
        return numNew != 0;
    }

4.addAll (int index, Collection c <Extends E?>): A collection of elements added in order to specify the position of the iteration

    public boolean addAll(int index, Collection<? extends E> c) {
        //判断index是否越界
        rangeCheckForAdd(index);

        //将集合c转为数组a
        Object[] a = c.toArray();

        //记录数组长度numNew
        int numNew = a.length;

        //判断是否需要扩容
        ensureCapacityInternal(size + numNew); 

        //计算需要移动的元素数量numMoved
        int numMoved = size - index;
        
        //如果numMoved>0,将index位置及其之后的元素后移numMoved个位置
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
    
        //将a数组中的元素赋值到从index位置开始的numMoved个位置上
        System.arraycopy(a, 0, elementData, index, numNew);

        //更新元素个数size为size+numNew
        size += numNew;
        return numNew != 0;
    }

5.remove (int index): Delete the specified position on the element O (n)

    public E remove(int index) {

        //判断index是否越界
        rangeCheck(index);

        modCount++;

        //将index位置上的元素记录下来
        E oldValue = elementData(index);

        //将index位置之后的元素前移(覆盖index位置上元素)
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);

        //将末尾元素置空(=null)
        elementData[--size] = null;

        //返回记录的index位置上的元素(oldValue)
        return oldValue;
    }

6.remove (Object o): Delete the first occurrence of a specified element

    public boolean remove(Object o) {

        //o如果为null,遍历数组并删除第一个为空的元素
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
        //o如果不为null,遍历数组并删除第一个与o相同的元素
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }

        //如果没有找到该元素,返回false
        return false;
    }

7.removeAll (Collection c <?>): Delete all of the elements contained in the specified collection

    public boolean removeAll(Collection<?> c) {

        //判断集合c是否为null,如果为null,抛出NullPointerException
        Objects.requireNonNull(c);

        return batchRemove(c, false);
    }

    private boolean batchRemove(Collection<?> c, boolean complement) {

        
        final Object[] elementData = this.elementData;

        //维护两个指针r,w,r用来遍历数组elementData,w用来记录不删除的元素存放位置
        int r = 0, w = 0;

        boolean modified = false;

        try {
            //遍历数组elementData中所有元素,依次判断是否存在于集合c中,如果没有,将其复制到w指针位置,w指针后移。
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            
            //判断r和w的位置,如果r没有移动到末尾(产生了异常中断了程序),将r指针及其之后的位置上的n元素向前移动到w指针位置,w指针后移n个位置。
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            //将w指针及其之后的元素置为null
            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;
    }

8.set (int index, E e): the elements on the specified position specified element is replaced with O (1)

    public E set(int index, E element) {

        //判断index是否越界
        rangeCheck(index);

        //将index位置上的元素记录下来
        E oldValue = elementData(index);

        //将e覆盖到index位置
        elementData[index] = element;

        //返回记录的index位置上的元素
        return oldValue;
    }

9.get (int index): Gets the element at the specified location

    public E get(int index) {

        //判断index是否越界
        rangeCheck(index);
        
        return elementData(index);
    }

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        //返回指定位置上的元素
        return (E) elementData[index];
    }

10.clear (): Delete all elements

    public void clear() {
        //修改计数+1
        modCount++;

        // 将所有元素置空
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

11.trimToSize (): set the capacity of the current element is the number of modified

    public void trimToSize() {
        //修改计数+1
        modCount++;

        //如果元素个数小于容量
        if (size < elementData.length) {

            //如果元素个数为0,将数组置为EMPTY_ELEMENTDATA,如果元素个数不为0,将数组长度调整为与元素个数相同
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

12.indexOf (Object o): Returns the index of the first occurrence in the collection of the specified element, if this list does not contain the element, or -1.

    public int indexOf(Object o) {

        //如果o为null,遍历数组并返回第一个为null的元素的位置
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {

         //如果o不为null,遍历数组并返回第一个与o相同的元素的下标
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }

        //如果没有找到,返回-1
        return -1;
    }

13.lastIndexOf (Object o): Returns the index of the last occurrence of the specified elements in this set, if the list does not contain the element, or -1.

    public int lastIndexOf(Object o) {

        //如果o为null,反序遍历数组并返回第一个为null的元素的位置
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {

        //如果o不为null,反序遍历数组并返回第一个与o相同的元素的下标
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        //如果没有找到,返回-1
        return -1;
    }

14.contains (Object o): if this list contains the specified element, it returns true.

    public boolean contains(Object o) {

        调用indexof(Object o),返回结果与0比较,返回比较结果。
        return indexOf(o) >= 0;
    }

 

Guess you like

Origin blog.csdn.net/QiuBika_061/article/details/90260994