JAVA 集合类(java.util)源码阅读笔记------ArrayList

来源:互联网 发布:java finalize 异常吗 编辑:程序博客网 时间:2024/05/20 14:43

一、继承关系

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

继承自AbstractList抽象类,实现List接口,RandomAccess接口,Cloneable接口, java.io.Serializable接口。

说明:
(1)RandomAccess:空接口,实现该接口代表该类拥有随机访问list对象的能力。
(2)Cloneable:空接口,实现该接口,重写Object的clone方法,否则会抛出异常。调用super.clone()实现对象的复制,如果对象中有引用,可以在super.clone后面进行处理。
(3)java.io.Serializable:空接口,实现该接口代表该类可序列化

类中的方法都是对List接口中方法的具体实现。

二、成员变量

private static final int DEFAULT_CAPACITY = 10;//默认的数组长度transient Object[] elementData;//存储list中元素的数组,transient关键字表示该对象在ArrayList序列化时不被序列化。private int size;//数组中实际元素的个数private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//数组的最大长度

三、重要方法说明

(1)clone: 保证复制ArrayList对象时,内部包含的elementData数组引用能重新申请空间创建数组,为深复制。
    public Object clone() {        try {            ArrayList<?> v = (ArrayList<?>) super.clone();//保证该clone是深复制,不加这句话,则复制的ArrayList对象中elementData指向的还是原对象中的数组。            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);        }    }


(2)toArray:传入参数,将elementData中数据存入的数组。若该数组的长度<size,则重新返回一个复制了elementData数据的该类型数组;否则直接将elementData中元素向a中复制,同时将a[size()]置为空,返回a。
@SuppressWarnings("unchecked")    public <T> T[] toArray(T[] a) {        if (a.length < size)            // Make a new array of a's runtime type, but my contents:            return (T[]) Arrays.copyOf(elementData, size, a.getClass());        System.arraycopy(elementData, 0, a, 0, size);        if (a.length > size)            a[size] = null;        return a;    }


(3)add:当数组长度不够时,需要动态扩容
    public boolean add(E e) {        ensureCapacityInternal(size + 1);  // size为element数组的实际大小,若size+1<elementData.length,则不用动态扩容,否则需要将elementData进行动态扩容。        elementData[size++] = e;        return true;    }private void ensureCapacityInternal(int minCapacity) {        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);        }        ensureExplicitCapacity(minCapacity);    }    private void ensureExplicitCapacity(int minCapacity) {        modCount++;        // overflow-conscious code        if (minCapacity - elementData.length > 0)            grow(minCapacity);    }grow:elementData数组扩容private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = elementData.length;//每次增长newCapacity=oldCapacity*1.5,为原来的1.5倍        int newCapacity = oldCapacity + (oldCapacity >> 1);//如果oldCapacity*1.5倍后,容量还是比minCapacity要小,则将newCapacity的值直接置为minCapacity        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;//如果增长的新长度大于了MAX_ARRAY_SIZE,则调用hugeCapacity来获取一个不大于Integer.MAX_VALUE的值。        if (newCapacity - MAX_ARRAY_SIZE > 0)            newCapacity = hugeCapacity(minCapacity);        // minCapacity is usually close to size, so this is a win://重新申请一个newCapacity长度的数组空间,并把elementData数组中内容拷贝过去。        elementData = Arrays.copyOf(elementData, newCapacity);    }hugeCapacity: elementData的最大容量private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0) // overflow            throw new OutOfMemoryError();//当最小保证的容量minCapacity比MAX_ARRAY_SIZE还大时,返回Integer.MAX_VALUE;否则直接返回MAX_ARRAY_SIZE        return (minCapacity > MAX_ARRAY_SIZE) ?            Integer.MAX_VALUE :            MAX_ARRAY_SIZE;    }


(4) add:在指定位置add一个元素
    public void add(int index, E element) {        rangeCheckForAdd(index);        ensureCapacityInternal(size + 1);  // 确保数组的长度>=size+1//将elementData中index到数组最后一个元素,整体向后移动一个位置,空出index这一个位置,将element填入        System.arraycopy(elementData, index, elementData, index + 1,                         size - index);        elementData[index] = element;        size++;    } public boolean addAll(int index, Collection<? extends E> c) {        rangeCheckForAdd(index);        Object[] a = c.toArray();        int numNew = a.length;//确保数组能容下添加的所有元素,可能进行动态扩容        ensureCapacityInternal(size + numNew);  // Increments modCount//计算从Index到处数组最后一个元素需要移动的元素的个数        int numMoved = size - index;        if (numMoved > 0)//直接采用System.arraycopy将elementData数组中从index开始到最后一个元素位置这一段数据,移动到index+numNew位置            System.arraycopy(elementData, index, elementData, index + numNew,                             numMoved);//若index等于size,则直接在原数组后面添加        System.arraycopy(a, 0, elementData, index, numNew);        size += numNew;        return numNew != 0;    }


(5)remove
//是一个前闭后开的区间,就是toIndex位置的元素不被移除,fromIndex位置元素被移除protected void removeRange(int fromIndex, int toIndex) {        modCount++;//需要移动的元素的个数=toIndex到最后一个元素位置        int numMoved = size - toIndex;        System.arraycopy(elementData, toIndex, elementData, fromIndex,                         numMoved);        // clear to let GC do its work        int newSize = size - (toIndex-fromIndex);        for (int i = newSize; i < size; i++) {            elementData[i] = null;//设置为null,让gc有机会回收        }        size = newSize;    }



(6)此外还提供了private void readObject(java.io.ObjectInputStream s)、 private void writeObject(java.io.ObjectOutputStream s)两个私有的序列化反序列化方法。



注意:
关于ArrayList中的Iterable(collection继承自此接口,所以collection的所有子类或者实现类都需要实现Iterator方法)接口中iterator()方法的实现
若一个线程在操作该ArrayList的iterator时,另一个线程对该ArrayList对象进行了添加修改删除更新操作,则会抛出new ConcurrentModificationException();
原因:http://www.cnblogs.com/skywang12345/p/3308762.html



原创粉丝点击