Source Analysis | ArrayList

1. What is ArrayLsit

ArrayList JDK is a linear set of classes based on a variable length array implemented and implements List interface.

2.ArrayList constructor analysis

When capacity is not specified

//创建ArrayList
ArrayList list = new ArrayList();

Once created, click into the ArrayList source code, it can be found

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

Such a constructor with no arguments to ArrayListperform the initialization operation, which elementDatais a Objecttype of array DEFAULTCAPACITY_EMPTY_ELEMENTDATAis a Objecttype 0 and a length of the array.

When the specified capacity

//创建ArrayList
ArrayList list = new ArrayList(20);

Click again you will find will call a constructor to initialize developed capacity

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

According to the code shows that after we pass parameters to create a capacity for the 20array. If not passed 20, but 0it would create a capacity of empty array, that is this.elementData = {}.

3.add () method

//创建ArrayList
ArrayList list = new ArrayList();
list.add("aaa");

After clicking to enter the following code can be found

public boolean add(E e) {
    //用于检测容量是否够用
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //将元素添加进集合中,并且维护size的值。  size的初始值为0
    elementData[size++] = e;
    return true;
}

Click ensureCapacityInternal(size + 1);you'll find the following code

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

As can be seen from the code is passed to the minimum space required additive element, and then click calculateCapacitymethod

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //DEFAULT_CAPACITY = 10
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

It found passed an Objectarray of type and minimum capacity. Because elementDataempty, it will enter the first ifdetermination, it will from 10和0selecting a maximum value among the results apparent, so 10 is returned to the ensureExplicitCapacityparameter list.

Then click ensureExplicitCapacity.

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

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

From here we can see that just passed will be a function of the expansion of 10 passes, and then clickgrow

private void grow(int minCapacity) {    //minCapacity = 10
    //elementData是一个空数组,所以oldCapacity为0
    int oldCapacity = elementData.length;
    // newCapacity = 0 + 0      所以newCapacity = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 0 - 10 < 0  true
    if (newCapacity - minCapacity < 0)
        // newCapacity = 10
        newCapacity = minCapacity;
    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);
}

Draw newCapacity = 10, and then call the copyOfmethod to copy, the copy is complete it will be elementDatathe length to 10.

Summary: In the first call to add () method, the capacity will be initialized to 10, but if you always add operation, expansion will reach the standard ArrayList again

Add to the list of elements to 11 times

    //创建ArrayList
    ArrayList list = new ArrayList();

    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");
    list.add("aaa");    //第11次调用add()方法

At this point we again perform the above operation until here

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

    // 11 - 10 > 0    true
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

Expansion of operations to perform again

private void grow(int minCapacity) {    //minCapacity = 11
    // oldCapacity = 10
    int oldCapacity = elementData.length;   
    //newCapacity = 10 + 10 / 2    15
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 15 - 11 < 0   false
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 进行copy
    elementData = Arrays.copyOf(elementData, newCapacity);
}

When performing the copy operation is completed to complete expansion, elememtDatathe capacity in this case 15

Summary: when the capacity of the capacity expansion for expansion will original 1.5 times

4.get () method

System.out.println(list.get(2));

getThe method need to pass array index, and returns the value in the array by the subscript. Click getmethod will show the following

public E get(int index) {
    //检查下标合法性,不合法则抛出异常
    rangeCheck(index);
    
    //直接返回数组中下标为index的元素
    return elementData(index);
}

5.set () method

list.set(2, "bbb");

Herein represents want to array index of the element is set to 2 bbb. click to enter

public E set(int index, E element) {
    //检查下标合法性
    rangeCheck(index);

    //保存索引为index位置的值
    E oldValue = elementData(index);
    //将传入的元素设置在index位置
    elementData[index] = element;
    //返回保存的元素
    return oldValue;
}

By passing the index and Etype of elements, updated after the completion of the original element values returned.

6.remove () method

System.out.println(list.remove(2));

Delete subscript 2 elements and returns the elements before they were removed, click the remove () method

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);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

7.iterator () method

    //创建ArrayList
    ArrayList list = new ArrayList();

    list.add("aaa");
    list.add("bbb");
    list.add("ccc");

    //创建迭代器
    Iterator it = list.iterator();
    //判断迭代器中是否还有下一个元素
    while (it.hasNext()){
        //将对象取出
        Object o = it.next();
        System.out.println(o);
    }

Iterator can traverse ArrayListthe elements, click oniterator()

public Iterator<E> iterator() {
    return new Itr();
}

Inside the iterator created an Itrobject and then click

//指向元素的游标,当前cursor = 0
int cursor;       // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;

Itr() {}

//迭代器中是否包含下一个元素
public boolean hasNext() {
    return cursor != size;
}

//将游标向后移动
public E next() {
    checkForComodification();
    int i = cursor;
    if (i >= size)
        throw new NoSuchElementException();
    Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length)
        throw new ConcurrentModificationException();
    //将cursor向后移动
    cursor = i + 1;
    return (E) elementData[lastRet = i];
}

After entering the above method and parameters of interest
to the added the above three elements, the sizethree, cursorand sizeare not equal, returns true, it will enter the whileloop and performing nextthe method, will first cursorassigned to i, i is 0 at this time, then the cursor backward Finally, the return movement of the element index 0. The cycle continues until it has been hasNextreturned false.

Released five original articles · won praise 0 · Views 27

Guess you like

Origin blog.csdn.net/xtxycyc/article/details/104477811