ArrayList source code analysisOne

All analysis is based on
the data structure of JDK15 ArrayList is an array. Array-based implementation. It is a thread-unsafe data structure. Implemented the List interface.
Insert picture description here

Attribute explanation

	 //默认ArrayList的容量
	 private static final int DEFAULT_CAPACITY = 10;
     /** 空数组实例 */
     private static final Object[] EMPTY_ELEMENTDATA = {
    
    };
     /** 共享的空数组实例 */
     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    
    };

     /** 数组元素数据 */
     transient Object[] elementData; 
     /** 数组元素个数 */
     private int size;

Constructor

ArrayList() constructs an empty list with an initial capacity of 10.
ArrayList​(int initialCapacity) Constructs an empty list with the specified initial capacity.
ArrayList​(Collection<? extends E> c) Constructs a list that contains the elements of the specified collection, the order of which is returned by the collection's iterator.

API

1 boolean add(E e) add element

public boolean add(E e) {
    
    
        modCount++;
        add(e, elementData, size);
        return true;
}

modCount is a property of AbstractList, the parent class of ArrayList. The main purpose is to not allow modifications to the collection structure when the iterator is iterating the collection. If any modification is made, a concurrent modification exception will be reported. Detailed follow-up.
The addition of add is done in the internal method add(e, elementData, size);.

private void add(E e, Object[] elementData, int s) {
    
    
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

If the number of elements is equal to the length of the array, expand the capacity, otherwise add elements directly. The length of the array element is +1. Look at the implementation of the expansion and call the grow() method.

private Object[] grow() {
    
    
        return grow(size + 1);
    }

It is also private and is implemented by calling grow(int minCapacity) internally. The parameter is the current capacity+1.

private Object[] grow(int minCapacity) {
    
    
		// 获取旧数组的长度
        int oldCapacity = elementData.length;
        //如果旧数组容量>0 或者不为空数组。就开始扩容
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
    
    
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
}

If it is an empty array, it returns the array with the minimum capacity and the maximum default capacity.

elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)

New capacity:

int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1

Call the ArraysSupport.newLength method to achieve.

public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    
    
        // assert oldLength >= 0
        // assert minGrowth > 0

        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
    
    
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }

Here prefGrowth is the preferred growth rate, and minGrowth is the minimum growth rate.
minGrowth=minCapacity-oldCapacity
prefGrowth=oldCapacity>>1=0.5oldCapacity. Therefore, the actual expanded length is 1.5 times the original array length. Finally, the array is copied.

elementData = Arrays.copyOf(elementData, newCapacity);

2 void add(int index, E element) Add the element to the specified position

public void add(int index, E element) {
    
    
		//检查索引是否超过数组长度
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = element;
        size = s + 1;
    }

First check whether the index is out of bounds, and then judge if the number of elements is equal to the length of the array, enter the logic. Expansion, then copy the old data, and then assign operations.

3 boolean addAll​(Collection<? extends E> c) add collection

public boolean addAll(Collection<? extends E> c) {
    
    
		//将集合转换为Object数组
        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        Object[] elementData;
        final int s;
        //如果添加元素的长度大于剩余数组的容量,开始扩容。然后复制数据
        if (numNew > (elementData = this.elementData).length - (s = size))
            elementData = grow(s + numNew);
        System.arraycopy(a, 0, elementData, s, numNew);
        size = s + numNew;
        return true;
    }

4 trimToSize() sets the current array capacity to the length of the element

public void trimToSize() {
    
    
        modCount++;
        if (size < elementData.length) {
    
    
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

5 ensureCapacity(int minCapacity) ensure capacity

If the capacity of ArrayList is not enough to hold all current elements, set new capacity=newLength = Math.max (minimum capacity-old array capacity, old array capacity/2) + old array capacity = 1.5 old array capacity

public void ensureCapacity(int minCapacity) {
    
    
        if (minCapacity > elementData.length
            && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                 && minCapacity <= DEFAULT_CAPACITY)) {
    
    
            modCount++;
            grow(minCapacity);
        }
    }

6 size() Get the number of array elements

public int size() {
    
    
      return size;
 }

7 isEmpty() Determine whether it is empty

public boolean isEmpty() {
    
    
        return size == 0;
}

8 indexOfRange () to find elements

int indexOfRange(Object o, int start, int end) {
    
    
        Object[] es = elementData;
        //如果为空,正向遍历
        if (o == null) {
    
    
            for (int i = start; i < end; i++) {
    
    
                if (es[i] == null) {
    
    
                    return i;
                }
            }
        } else {
    
    
        //不为空,直接遍历
            for (int i = start; i < end; i++) {
    
    
                if (o.equals(es[i])) {
    
    
                    return i;
                }
            }
        }
        return -1;
    }

9 contains determines whether to include an element

public boolean contains(Object o) {
    
    
		//调用index()方法正向查找
        return indexOf(o) >= 0;
    }

10 indexOf() forward search

public int indexOf(Object o) {
    
    
        return indexOfRange(o, 0, size);
    }

11 lastIndexOf () reverse search

 public int lastIndexOf(Object o) {
    
    
        return lastIndexOfRange(o, 0, size);
    }

12 clone

public Object clone() {
    
    
        try {
    
    
        	//调用父类的克隆方法,克隆空的ArrayList实例
            ArrayList<?> v = (ArrayList<?>) super.clone();
            //复制数组,然后赋值
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
    
    
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

13 Object[] toArray() converted to an array

public Object[] toArray() {
    
    
        return Arrays.copyOf(elementData, size);
    }

14 get(int index) Get the element

 public E get(int index) {
    
    
        Objects.checkIndex(index, size);
        return elementData(index);
    }

15 remove(int index) deletes the element at the specified position

public E remove(int index) {
    
    
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

Guess you like

Origin blog.csdn.net/GoSaint/article/details/113871542