Android源码之ArrayList

来源:互联网 发布:控制台运行java程序 编辑:程序博客网 时间:2024/05/01 09:54

今天是上班后的第一天,由于项目正在测试阶段,比较空闲,所以研究了一下Android中的ArrayList源码,先说明本篇文章是基于android-23进行的分析,因为我看到网上很多的arrayList源码和我看到的android源码不一样。

首先我们看下Java集合框架中的继承图。
这里写图片描述

由于今天主要讲的是ArrayList,以后的类我会在以后一一分析。那现在就开始我们今天的源码阅读。

1:我们都知道arraylist是基于数组实现的,是一个动态的数组,其容量能够自动的增长,
2:ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
3:ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传送,实现了RandowAccess接口,支持快速随机访问,实现了Cloneable接口,能被克隆。

public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, RandomAccess {   //默认的最小的增加数量    private static final int MIN_CAPACITY_INCREMENT = 12;   //ArrayList中的个数    int size;    //当前的数组    transient Object[] array;    //初始化array,EmptyArray.OBJECT是长度为0的数组    public ArrayList(int capacity) {        if (capacity < 0) {            throw new IllegalArgumentException("capacity < 0: " + capacity);        }        array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);    }    //EmptyArray.OBJECT是长度为0的数组    public ArrayList() {        array = EmptyArray.OBJECT;    }    //初始化传进来的collection长度的数组    public ArrayList(Collection<? extends E> collection) {        if (collection == null) {            throw new NullPointerException("collection == null");        }        Object[] a = collection.toArray();        if (a.getClass() != Object[].class) {            Object[] newArray = new Object[a.length];            System.arraycopy(a, 0, newArray, 0, a.length);            a = newArray;        }        array = a;        size = a.length;    }    @Override public boolean add(E object) {        Object[] a = array;        int s = size;        if (s == a.length) {        //s小于6的话,设置newArray的长度为s+12,不然的话newArray的长度是1.5倍的s            Object[] newArray = new Object[s +                    (s < (MIN_CAPACITY_INCREMENT / 2) ?                     MIN_CAPACITY_INCREMENT : s >> 1)];            System.arraycopy(a, 0, newArray, 0, s);            array = a = newArray;        }        a[s] = object;        size = s + 1;        modCount++;        return true;    }    //添加对象到指定的位置    @Override public void add(int index, E object) {        Object[] a = array;        int s = size;        if (index > s || index < 0) {            throwIndexOutOfBoundsException(index, s);        }        //长度小于a的话,直接添加        if (s < a.length) {            System.arraycopy(a, index, a, index + 1, s - index);        } else {            //长度大于a的话,又是编程原来的1.5倍            Object[] newArray = new Object[newCapacity(s)];            //index位置前面的copy            System.arraycopy(a, 0, newArray, 0, index);            //index位置后面的copy            System.arraycopy(a, index, newArray, index + 1, s - index);            array = a = newArray;        }        //赋值当前的index值为object        a[index] = object;        size = s + 1;        modCount++;    }    //判断当前的数组长度,若小于6.则增长值为12,不然的话增长值为把数组的长度*2    private static int newCapacity(int currentCapacity) {        int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?                MIN_CAPACITY_INCREMENT : currentCapacity >> 1);        return currentCapacity + increment;    }    //添加一个集合到当前的集合中    @Override public boolean addAll(Collection<? extends E> collection) {        Object[] newPart = collection.toArray();        int newPartSize = newPart.length;        if (newPartSize == 0) {            return false;        }        Object[] a = array;        int s = size;        int newSize = s + newPartSize; // If add overflows, arraycopy will fail        if (newSize > a.length) {            int newCapacity = newCapacity(newSize - 1);  // ~33% growth room            Object[] newArray = new Object[newCapacity];            System.arraycopy(a, 0, newArray, 0, s);            array = a = newArray;        }        System.arraycopy(newPart, 0, a, s, newPartSize);        size = newSize;        modCount++;        return true;    }    //添加集合到指定的位置    @Override    public boolean addAll(int index, Collection<? extends E> collection) {        int s = size;        if (index > s || index < 0) {            throwIndexOutOfBoundsException(index, s);        }        Object[] newPart = collection.toArray();        int newPartSize = newPart.length;        if (newPartSize == 0) {            return false;        }        Object[] a = array;        int newSize = s + newPartSize; // If add overflows, arraycopy will fail        if (newSize <= a.length) {             System.arraycopy(a, index, a, index + newPartSize, s - index);        } else {            int newCapacity = newCapacity(newSize - 1);  // ~33% growth room            Object[] newArray = new Object[newCapacity];            System.arraycopy(a, 0, newArray, 0, index);            System.arraycopy(a, index, newArray, index + newPartSize, s-index);            array = a = newArray;        }        System.arraycopy(newPart, 0, a, index, newPartSize);        size = newSize;        modCount++;        return true;    }    static IndexOutOfBoundsException throwIndexOutOfBoundsException(int index, int size) {        throw new IndexOutOfBoundsException("Invalid index " + index + ", size is " + size);    }    //移除当前数组的内容,每个字都会编程null,然后设置size=0    @Override public void clear() {        if (size != 0) {            Arrays.fill(array, 0, size, null);            size = 0;            modCount++;        }    }    @Override public Object clone() {        try {            ArrayList<?> result = (ArrayList<?>) super.clone();            result.array = array.clone();            return result;        } catch (CloneNotSupportedException e) {           throw new AssertionError();        }    }    //保证当前数组能够容纳    public void ensureCapacity(int minimumCapacity) {        Object[] a = array;        if (a.length < minimumCapacity) {            Object[] newArray = new Object[minimumCapacity];            System.arraycopy(a, 0, newArray, 0, size);            array = newArray;            modCount++;        }    }    @Override     public E get(int index) {        if (index >= size) {            throwIndexOutOfBoundsException(index, size);        }        return (E) array[index];    }    @Override public int size() {        return size;    }    @Override public boolean isEmpty() {        return size == 0;    }    @Override public boolean contains(Object object) {        Object[] a = array;        int s = size;        if (object != null) {            for (int i = 0; i < s; i++) {                if (object.equals(a[i])) {                    return true;                }            }        } else {            for (int i = 0; i < s; i++) {                if (a[i] == null) {                    return true;                }            }        }        return false;    }    @Override public int indexOf(Object object) {        Object[] a = array;        int s = size;        if (object != null) {            for (int i = 0; i < s; i++) {                if (object.equals(a[i])) {                    return i;                }            }        } else {            for (int i = 0; i < s; i++) {                if (a[i] == null) {                    return i;                }            }        }        return -1;    }    @Override public int lastIndexOf(Object object) {        Object[] a = array;        if (object != null) {            for (int i = size - 1; i >= 0; i--) {                if (object.equals(a[i])) {                    return i;                }            }        } else {            for (int i = size - 1; i >= 0; i--) {                if (a[i] == null) {                    return i;                }            }        }        return -1;    }    @Override public E remove(int index) {        Object[] a = array;        int s = size;        if (index >= s) {            throwIndexOutOfBoundsException(index, s);        }        @SuppressWarnings("unchecked") E result = (E) a[index];        System.arraycopy(a, index + 1, a, index, --s - index);        a[s] = null;  // Prevent memory leak        size = s;        modCount++;        return result;    }    @Override public boolean remove(Object object) {        Object[] a = array;        int s = size;        if (object != null) {            for (int i = 0; i < s; i++) {                if (object.equals(a[i])) {                    System.arraycopy(a, i + 1, a, i, --s - i);                    a[s] = null;  // Prevent memory leak                    size = s;                    modCount++;                    return true;                }            }        } else {            for (int i = 0; i < s; i++) {                if (a[i] == null) {                    System.arraycopy(a, i + 1, a, i, --s - i);                    a[s] = null;  // Prevent memory leak                    size = s;                    modCount++;                    return true;                }            }        }        return false;    }    @Override protected void removeRange(int fromIndex, int toIndex) {        if (fromIndex == toIndex) {            return;        }        Object[] a = array;        int s = size;        if (fromIndex >= s) {            throw new IndexOutOfBoundsException("fromIndex " + fromIndex                    + " >= size " + size);        }        if (toIndex > s) {            throw new IndexOutOfBoundsException("toIndex " + toIndex                    + " > size " + size);        }        if (fromIndex > toIndex) {            throw new IndexOutOfBoundsException("fromIndex " + fromIndex                    + " > toIndex " + toIndex);        }        System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);        int rangeSize = toIndex - fromIndex;        Arrays.fill(a, s - rangeSize, s, null);        size = s - rangeSize;        modCount++;    }    @Override public E set(int index, E object) {        Object[] a = array;        if (index >= size) {            throwIndexOutOfBoundsException(index, size);        }        @SuppressWarnings("unchecked") E result = (E) a[index];        a[index] = object;        return result;    }    @Override public Object[] toArray() {        int s = size;        Object[] result = new Object[s];        System.arraycopy(array, 0, result, 0, s);        return result;    }    @Override public <T> T[] toArray(T[] contents) {        int s = size;        if (contents.length < s) {            @SuppressWarnings("unchecked") T[] newArray                = (T[]) Array.newInstance(contents.getClass().getComponentType(), s);            contents = newArray;        }        System.arraycopy(this.array, 0, contents, 0, s);        if (contents.length > s) {            contents[s] = null;        }        return contents;    }    public void trimToSize() {        int s = size;        if (s == array.length) {            return;        }        if (s == 0) {            array = EmptyArray.OBJECT;        } else {            Object[] newArray = new Object[s];            System.arraycopy(array, 0, newArray, 0, s);            array = newArray;        }        modCount++;    }    @Override public Iterator<E> iterator() {        return new ArrayListIterator();    }    private class ArrayListIterator implements Iterator<E> {        /** Number of elements remaining in this iteration */        private int remaining = size;        /** Index of element that remove() would remove, or -1 if no such elt */        private int removalIndex = -1;        /** The expected modCount value */        private int expectedModCount = modCount;        public boolean hasNext() {            return remaining != 0;        }        @SuppressWarnings("unchecked") public E next() {            ArrayList<E> ourList = ArrayList.this;            int rem = remaining;            if (ourList.modCount != expectedModCount) {                throw new ConcurrentModificationException();            }            if (rem == 0) {                throw new NoSuchElementException();            }            remaining = rem - 1;            return (E) ourList.array[removalIndex = ourList.size - rem];        }        public void remove() {            Object[] a = array;            int removalIdx = removalIndex;            if (modCount != expectedModCount) {                throw new ConcurrentModificationException();            }            if (removalIdx < 0) {                throw new IllegalStateException();            }            System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);            a[--size] = null;  // Prevent memory leak            removalIndex = -1;            expectedModCount = ++modCount;        }    }    @Override public int hashCode() {        Object[] a = array;        int hashCode = 1;        for (int i = 0, s = size; i < s; i++) {            Object e = a[i];            hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());        }        return hashCode;    }    @Override public boolean equals(Object o) {        if (o == this) {            return true;        }        if (!(o instanceof List)) {            return false;        }        List<?> that = (List<?>) o;        int s = size;        if (that.size() != s) {            return false;        }        Object[] a = array;        if (that instanceof RandomAccess) {            for (int i = 0; i < s; i++) {                Object eThis = a[i];                Object ethat = that.get(i);                if (eThis == null ? ethat != null : !eThis.equals(ethat)) {                    return false;                }            }        } else {  // Argument list is not random access; use its iterator            Iterator<?> it = that.iterator();            for (int i = 0; i < s; i++) {                Object eThis = a[i];                Object eThat = it.next();                if (eThis == null ? eThat != null : !eThis.equals(eThat)) {                    return false;                }            }        }        return true;    }    private static final long serialVersionUID = 8683452581122892189L;    private void writeObject(ObjectOutputStream stream) throws IOException {        stream.defaultWriteObject();        stream.writeInt(array.length);        for (int i = 0; i < size; i++) {            stream.writeObject(array[i]);        }    }    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {        stream.defaultReadObject();        int cap = stream.readInt();        if (cap < size) {            throw new InvalidObjectException(                    "Capacity: " + cap + " < size: " + size);        }        array = (cap == 0 ? EmptyArray.OBJECT : new Object[cap]);        for (int i = 0; i < size; i++) {            array[i] = stream.readObject();        }    } }

1、注意其三个不同的构造方法。无参构造方法构造的ArrayList的容量默认为0,带有Collection参数的构造方法,将Collection转化为数组赋给ArrayList的实现。

2、注意扩充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当容量不足以容纳当前的元素个数时,就设置新的容量为旧的容量的1.5倍,如果设置后的新容量还不够,则直接新容量设置为传入的参数(也就是所需的容量),而后用Arrays.copyof()方法将元素拷贝到新的数组(详见下面的第3点)。从中可以看出,当容量不够时,每次增加元素,都要将原来的元素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList。

3、ArrayList的实现中大量地调用了Arrays.copyof()和System.arraycopy()方法。
看System.arraycopy()方法,该方法被标记了native,调用了系统的C/C++代码,在JDK中是看不到的,但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,因此它可以保证同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时用该方法,以取得更高的效率。

4、注意ArrayList的两个转化为静态数组的toArray方法。
第一个,Object[] toArray()方法。该方法有可能会抛出java.lang.ClassCastException异常,如果直接用向下转型的方法,将整个ArrayList集合转变为指定类型的Array数组,便会抛出该异常,而如果转化为Array数组时不向下转型,而是将每个元素向下转型,则不会抛出该异常,显然对数组中的元素一个个进行向下转型,效率不高,且不太方便。
第二个, T[] toArray(T[] a)方法。该方法可以直接将ArrayList转换得到的Array进行整体向下转型(转型其实是在该方法的源码中实现的),且从该方法的源码中可以看出,参数a的大小不足时,内部会调用Arrays.copyOf方法,该方法内部创建一个新的数组返回。

5、ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低,建议使用LinkedList。

6、在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null。

0 0