JDK源码 -- ArrayList

一、概念

类定义:

public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
  • 继承了AbstractList抽象类,实现了List接口,拥有一组List通用的操作。
  • 实现了RandomAccess接口,可进行随机访问。
  • 实现了Cloneable接口,可进行浅层次拷贝。
  • 实现了Serializable接口,可进行序列化。

特点:

  • 长于随机访问元素。
  • 在List中间插入和删除元素较慢。

二、使用

//TestArrayList
public class TestArrayList {
    private static final String TAG = "TestArrayList";
    private ArrayList list = new ArrayList<>();

    public void testAdd() {
        list.add("a");
        list.add("b");
        list.add("c");
        Log.d(TAG, "zwm, add list: " + list);
    }

    public void testGet() {
        Log.d(TAG, "zwm, get index 2: " + list.get(2));
    }

    public void testAdd2() {
        list.add(0, "ii");
        list.add(1, "jj");
        list.add(2, "kk");
        Log.d(TAG, "zwm, add index list: " + list);
    }

    public void testAddAll() {
        ArrayList temp = new ArrayList<>();
        temp.add("lll");
        temp.add("mmm");
        temp.add("nnn");
        list.addAll(temp);
        Log.d(TAG, "zwm, addAll list: " + list);
    }

    public void testAddAll2() {
        ArrayList temp = new ArrayList<>();
        temp.add("xxxx");
        temp.add("zzzz");
        temp.add("yyyy");
        temp.add("zzzz");
        list.addAll(0, temp);
        Log.d(TAG, "zwm, addAll index list: " + list);
    }

    public void testIndexOf() {
        Log.d(TAG, "zwm, indexOf zzzz: " + list.indexOf("zzzz"));
    }

    public void testLastIndexOf() {
        Log.d(TAG, "zwm, lastIndexOf zzzz: " + list.lastIndexOf("zzzz"));
    }

    public void testClone() {
        ArrayList cloneList = (ArrayList)list.clone();
        Log.d(TAG, "zwm, list.equals(cloneList): " + list.equals(cloneList));
        Log.d(TAG, "zwm, list==cloneList: " + (list==cloneList));
    }

    public void testContains() {
        Log.d(TAG, "zwm, contains zzzz: " + list.contains("zzzz"));
    }

    public void testContainsAll() {
        ArrayList temp = new ArrayList<>();
        temp.add("xxxx");
        temp.add("yyyy");
        temp.add("zzzz");
        Log.d(TAG, "zwm, containsAll: " + list.containsAll(temp));
    }

    public void testSize() {
        Log.d(TAG, "zwm, size: " + list.size());
    }

    public void testClear() {
        list.clear();
        Log.d(TAG, "zwm, clear list: " + list);
    }

    public void testEmpty() {
        Log.d(TAG, "zwm, isEmpty: " + list.isEmpty());
    }

    public void testIterator() {
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Log.d(TAG, "zwm, iterator item: " + iterator.next());
        }
    }

    public void testIterator2() {
        ListIterator iterator = list.listIterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            Log.d(TAG, "zwm, listIterator item: " + item);
            if(TextUtils.equals(item, "b")) {
                Log.d(TAG, "zwm, remove b");
                iterator.remove();
            } else if(TextUtils.equals(item, "c")) {
                Log.d(TAG, "zwm, update c to x");
                iterator.set("x");
            }
        }
        Log.d(TAG, "zwm, listIterator list: " + list);
        Log.d(TAG, "zwm, next index: " + iterator.nextIndex());
        Log.d(TAG, "zwm, previous index: " + iterator.previousIndex());
        while(iterator.hasPrevious()) {
            String item = iterator.previous();
            Log.d(TAG, "zwm, listIterator item: " + item);
        }
    }

    public void testIterator3() {
        ListIterator iterator = list.listIterator(2);
        while (iterator.hasNext()) {
            String item = iterator.next();
            Log.d(TAG, "zwm, listIterator index item: " + item);
        }
    }

    public void testRemove() {
        Log.d(TAG, "zwm, remove a: " + list.remove("a"));
        Log.d(TAG, "zwm, remove list: " + list);
    }

    public void testRemove2() {
        Log.d(TAG, "zwm, remove index 3: " + list.remove(3));
        Log.d(TAG, "zwm, remove index list: " + list);
    }

    public void testRemoveAll() {
        ArrayList temp = new ArrayList<>();
        temp.add("a");
        temp.add("b");
        Log.d(TAG, "zwm, removeAll: " + list.removeAll(temp));
        Log.d(TAG, "zwm, removeAll list: " + list);
    }

    public void testRetainAll() {
        ArrayList temp = new ArrayList<>();
        temp.add("a");
        temp.add("b");
        temp.add("c");
        Log.d(TAG, "zwm, retainAll: " + list.retainAll(temp));
        Log.d(TAG, "zwm, retainAll list: " + list);
    }

    public void testSet() {
        list.set(0, "sss");
        Log.d(TAG, "zwm, set list: " + list);
    }

    public void testSubList() {
        //以下注释语句会抛出异常java.lang.ClassCastException: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList
        //ArrayList subList = (ArrayList)list.subList(1, 2);
         List subList = list.subList(1, 3);
        Log.d(TAG, "zwm, subList: " + subList);
    }

    public void testEnsureCapacity() {
        //在数据量过大的情况下初始化理想的ArryList容量,效率会明显高于自动扩容
        //所以在项目中有些业务处理时候对ArryList的长度有明显的把控时 最好自定义其扩容方法来提高程序的执行效率
        Log.d(TAG, "zwm, ensureCapacity");
        list.ensureCapacity(100);
    }

    public void testTrimToSize() {
        //将ArrayList容量设置为实际大小
        Log.d(TAG, "zwm, trimToSize");
        list.trimToSize();
    }

    public void testToArray() {
        Object[] arrays = list.toArray();
        for(Object item : arrays) {
            Log.d(TAG, "zwm, toArray item: " + item);
        }
    }

    public void testToArray2() {
        String[] param = new String[list.size()];
        String[] result = list.toArray(param);
        for(String item : param) {
            Log.d(TAG, "zwm, toArray T param item: " + item);
        }
        for(String item : result) {
            Log.d(TAG, "zwm, for result T result item: " + item);
        }
    }
}

//测试代码
private void testMethod() {
    Log.d(TAG, "zwm, testMethod");
    TestArrayList testArrayList = new TestArrayList();
    testArrayList.testAdd();
    testArrayList.testAdd2();
    testArrayList.testAddAll();
    testArrayList.testAddAll2();
    testArrayList.testGet();
    testArrayList.testIndexOf();
    testArrayList.testLastIndexOf();
    testArrayList.testClone();
    testArrayList.testContains();
    testArrayList.testContainsAll();
    testArrayList.testSize();
    testArrayList.testClear();
    testArrayList.testEmpty();
    testArrayList.testAdd();
    testArrayList.testIterator();
    testArrayList.testIterator2();
    testArrayList.testAdd();
    testArrayList.testIterator3();
    testArrayList.testEnsureCapacity();
    testArrayList.testRemove();
    testArrayList.testRemove2();
    testArrayList.testRemoveAll();
    testArrayList.testAdd();
    testArrayList.testRetainAll();
    testArrayList.testSet();
    testArrayList.testSubList();
    testArrayList.testTrimToSize();
    testArrayList.testToArray();
    testArrayList.testToArray2();
}

//输出log
2019-08-02 18:31:06.908 zwm, testMethod
2019-08-02 18:31:06.911 zwm, add list: [a, b, c]
2019-08-02 18:31:06.912 zwm, add index list: [ii, jj, kk, a, b, c]
2019-08-02 18:31:06.912 zwm, addAll list: [ii, jj, kk, a, b, c, lll, mmm, nnn]
2019-08-02 18:31:06.913 zwm, addAll index list: [xxxx, zzzz, yyyy, zzzz, ii, jj, kk, a, b, c, lll, mmm, nnn]
2019-08-02 18:31:06.913 zwm, get index 2: yyyy
2019-08-02 18:31:06.913 zwm, indexOf zzzz: 1
2019-08-02 18:31:06.913 zwm, lastIndexOf zzzz: 3
2019-08-02 18:31:06.914 zwm, list.equals(cloneList): true
2019-08-02 18:31:06.914 zwm, list==cloneList: false
2019-08-02 18:31:06.914 zwm, contains zzzz: true
2019-08-02 18:31:06.914 zwm, containsAll: true
2019-08-02 18:31:06.914 zwm, size: 13
2019-08-02 18:31:06.914 zwm, clear list: []
2019-08-02 18:31:06.915 zwm, isEmpty: true
2019-08-02 18:31:06.915 zwm, add list: [a, b, c]
2019-08-02 18:31:06.915 zwm, iterator item: a
2019-08-02 18:31:06.915 zwm, iterator item: b
2019-08-02 18:31:06.915 zwm, iterator item: c
2019-08-02 18:31:06.915 zwm, listIterator item: a
2019-08-02 18:31:06.915 zwm, listIterator item: b
2019-08-02 18:31:06.915 zwm, remove b
2019-08-02 18:31:06.916 zwm, listIterator item: c
2019-08-02 18:31:06.916 zwm, update c to x
2019-08-02 18:31:06.916 zwm, listIterator list: [a, x]
2019-08-02 18:31:06.916 zwm, next index: 2
2019-08-02 18:31:06.916 zwm, previous index: 1
2019-08-02 18:31:06.916 zwm, listIterator item: x
2019-08-02 18:31:06.916 zwm, listIterator item: a
2019-08-02 18:31:06.916 zwm, add list: [a, x, a, b, c]
2019-08-02 18:31:06.917 zwm, listIterator index item: a
2019-08-02 18:31:06.917 zwm, listIterator index item: b
2019-08-02 18:31:06.917 zwm, listIterator index item: c
2019-08-02 18:31:06.917 zwm, ensureCapacity
2019-08-02 18:31:06.917 zwm, remove a: true
2019-08-02 18:31:06.917 zwm, remove list: [x, a, b, c]
2019-08-02 18:31:06.918 zwm, remove index 3: c
2019-08-02 18:31:06.918 zwm, remove index list: [x, a, b]
2019-08-02 18:31:06.918 zwm, removeAll: true
2019-08-02 18:31:06.918 zwm, removeAll list: [x]
2019-08-02 18:31:06.918 zwm, add list: [x, a, b, c]
2019-08-02 18:31:06.919 zwm, retainAll: true
2019-08-02 18:31:06.919 zwm, retainAll list: [a, b, c]
2019-08-02 18:31:06.919 zwm, set list: [sss, b, c]
2019-08-02 18:31:06.919 zwm, subList: [b, c]
2019-08-02 18:31:06.920 zwm, trimToSize
2019-08-02 18:31:06.920 zwm, toArray item: sss
2019-08-02 18:31:06.920 zwm, toArray item: b
2019-08-02 18:31:06.920 zwm, toArray item: c
2019-08-02 18:31:06.920 zwm, toArray T param item: sss
2019-08-02 18:31:06.920 zwm, toArray T param item: b
2019-08-02 18:31:06.920 zwm, toArray T param item: c
2019-08-02 18:31:06.920 zwm, toArray T result item: sss
2019-08-02 18:31:06.920 zwm, toArray T result item: b
2019-08-02 18:31:06.921 zwm, toArray T result item: c

三、原理

重要参数

//默认的数组长度
private static final int DEFAULT_CAPACITY = 10;

//默认的空数组
private static final Object[] EMPTY_ELEMENTDATA = {};

//默认的空数组(与EMPTY_ELEMENTDATA有点区别,在不同的构造函数中用到)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//真正用于存放数据的数组
transient Object[] elementData; 

//数组元素个数
private int size;

构造函数

//指定容量大小初始化
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);
    }
}

//无参初始化,DEFAULTCAPACITY_EMPTY_ELEMENTDATA与EMPTY_ELEMENTDATA都是空数组,区别是当第一个元素被插入时,如果使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组,会自动将容量扩容到10
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

//构造一个包含指定Collection的元素的列表,这些元素是按照该Collection的迭代器返回它们的顺序排列的
public ArrayList(Collection c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

public void trimToSize()

//将ArrayList容量设置为实际大小
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size); //拷贝数组elementData,新数组大小为size
    }
}

public void ensureCapacity(int minCapacity)

//在数据量过大的情况下初始化理想的ArryList容量,效率会明显高于自动扩容
//所以在项目中有些业务处理时候对ArryList的长度有明显的把控时 最好自定义其扩容方法来提高程序的执行效率
public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 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) //如果指定的minCapacity数值比当前数组容量大,则进行扩容
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); //newCapacity赋值为oldCapacity * 1.5
    if (newCapacity - minCapacity < 0) //如果newCapacity小于指定的minCapacity数值,则newCapacity赋值为minCapacity
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0) //如果newCapacity大于MAX_ARRAY_SIZE
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity); //拷贝数组elementData,新数组大小为newCapacity
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ? //如果指定的minCapacity数值大于MAX_ARRAY_SIZE,则扩容至Integer.MAX_VALUE,否则使用MAX_ARRAY_SIZE
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

private void ensureCapacityInternal(int minCapacity)

//在相关操作之前,确保数组有足够的容量
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

public boolean add(E e)

//添加一个元素在数组末尾
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

public void add(int index, E element)

//在索引位置插入元素
public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1, //将index及后面的数据后移一位
                     size - index);
    elementData[index] = element; //插入元素到index位置
    size++; //元素个数加1
}

//判断索引是否越界
private void rangeCheckForAdd(int index) { 
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

public boolean addAll(Collection c)

//插入Collection中的所有元素到末尾
public boolean addAll(Collection c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew); //拷贝数组a的numNew个元素到数组elementData的末尾
    size += numNew; //元素个数加numNew
    return numNew != 0;
}

public boolean addAll(int index, Collection c)

//在索引位置插入Collection中的所有元素
public boolean addAll(int index, Collection 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, //将index及后面的数据后移numNew位
                         numMoved);

    System.arraycopy(a, 0, elementData, index, numNew); //拷贝数组a的numNew个元素到数组elementData的以index开始的numNew个位置
    size += numNew;
    return numNew != 0;
}

public E remove(int index)

//输出索引位置的元素
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, //将index后面的元素前移一位
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

public boolean remove(Object o)

//删除与对象o相等的元素
public boolean remove(Object o) {
    if (o == null) { //要删除的为空对象
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) { //判断是否等于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) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0) 
        System.arraycopy(elementData, index+1, elementData, index, //将index后面的元素前移一位
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}

public boolean removeAll(Collection c)

//删除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++)
            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;
}

public E set(int index, E element)

//修改索引位置的元素
public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

public E get(int index)

//查询索引位置的元素
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

public int indexOf(Object o)

//查询第一个与对象o相等的元素的索引位置
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;
}

public int lastIndexOf(Object o)

//查询最后一个与对象o相等的元素的索引位置
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;
}

public boolean contains(Object o)

//查询是否包含与对象o相等的元素
public boolean contains(Object o) {
    return indexOf(o) >= 0; //调用indexof方法
}

public void clear()

//清空数组
public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

public int size()

//获取数组元素个数
public int size() {
    return size;
}

public boolean isEmpty()

//判断数组是否有元素
public boolean isEmpty() {
    return size == 0;
}

public Iterator iterator()

//返回迭代器对象
public Iterator iterator() {
    return new Itr();
}

//迭代器类,实现了Iterator接口
private class Itr implements Iterator {
    //获取下一个元素
    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 = i + 1;
        return (E) elementData[lastRet = i];
    }

    //移除当前元素
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
    
    //确认是否在别的线程有修改集合
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }   
}

fail-fast机制:
在next和remove操作之前,都会调用checkForComodification函数,如果modCount和本身记录的expectedModCount不一致,就证明集合在别处被修改过,抛出ConcurrentModificationException异常,产生fail-fast事件。

fail-fast机制是java集合(Collection)中的一种错误机制,当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了,那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。一般在多线程环境下,可以考虑使用CopyOnWriteArrayList来避免fail-fast。

public ListIterator listIterator()

//返回迭代器对象
public ListIterator listIterator() {
    return new ListItr(0);
}

//迭代器类,实现了ListIterator接口
private class ListItr extends Itr implements ListIterator

四、主题

数组

你可能感兴趣的:(JDK源码 -- ArrayList)