ArrayList源码解读

来源:互联网 发布:mac磁盘分区 编辑:程序博客网 时间:2024/06/02 21:47

ArrayList源码分析

ArrayList特点总结

  • ArrayList实现List接口,底层是使用数组实现的,可以根据元素的个数进行动态扩容
  • ArrayList线程不安全而Vector是线程安全的,多线程环境下,可以考虑使用

    List list = Collections.synchronizedList(new ArrayList(...));

  • 元素可以是null
  • 查询修改元素的时间复杂度O(1),而插入删除为O(n)
  • 构造方法 有3种 一种是指定list的容量 一种是无参构造方法 还有一种是使用一个Collection为参数
  • 扩容方法 见grow方法 int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容当前数组长度的一半 1.8之前是 newCapacity = (oldCapacity * 3)/2+1

源码分析

为了代码的简洁,将非核心的代码去掉了,这里还是想说英文的注释是最好的学习材料,有条件的还是应该多看源码中的英文注释

public class ArrayList<E> extends AbstractList<E>        implements List<E>, RandomAccess, Cloneable, java.io.Serializable{   //实现List接口 //实现RandomAccess接口,可以进行随机访问 //实现Cloneable接口,可以被clone //实现序列化接口    private static final long serialVersionUID = 8683452581122892189L;    //默认的初始容量是10,也就是数组的大小默认是10,面试时会问问    private static final int DEFAULT_CAPACITY = 10;    //两个空的数组对应不同的构造方法    private static final Object[] EMPTY_ELEMENTDATA = {};    //默认容量的空数组    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};     //存储ArrayList元素的数组     //任何一个空的ArrayList(使用elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA进行初始化的,     //在第一个元素被add的时候都会自动扩容到DEFAULT_CAPACITY)     //使用transient时为了不被序列化    transient Object[] elementData;    //ArrayList中元素的个数    private int size;    //构造方法    public ArrayList(int initialCapacity) {        if (initialCapacity > 0) { //初始化容量            this.elementData = new Object[initialCapacity];        } else if (initialCapacity == 0) { //当初始化容量为0的时候 elementData = {}            this.elementData = EMPTY_ELEMENTDATA;        } else { //初始化容量<0时 抛出异常            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        }    }    //无参构造方法,elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA 当第一个元素被添加的时候扩容到10    //jdk1.7的时候 好像是this(10)    public ArrayList() {         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;    }    //构造方法 参数是一个Collection对象    public ArrayList(Collection<? extends E> c) {        elementData = c.toArray(); //将c转成数组对象        if ((size = elementData.length) != 0) {             // 判断elementData的类型 因为c.toArray不一定返回的Object[] 见            // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6260652            if (elementData.getClass() != Object[].class)                elementData = Arrays.copyOf(elementData, size, Object[].class);        } else {            // 替换空数组            this.elementData = EMPTY_ELEMENTDATA;        }    }    //将数组中的元素剔除,这样可以使ArrayList实例占用的存储空间尽可能小    public void trimToSize() {        modCount++;        if (size < elementData.length) {            elementData = (size == 0)              ? EMPTY_ELEMENTDATA              : Arrays.copyOf(elementData, size);        }    }     //判断当前ArrayList的容量是否够用    public void ensureCapacity(int minCapacity) {        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)            ? 0 : DEFAULT_CAPACITY;        if (minCapacity > minExpand) {            ensureExplicitCapacity(minCapacity);        }    }    private void ensureCapacityInternal(int minCapacity) {        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {            //minCapacity为默认大小10和参数指定大小的较大值            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);        }        ensureExplicitCapacity(minCapacity);    }    private void ensureExplicitCapacity(int minCapacity) {        modCount++;        if (minCapacity - elementData.length > 0)            //如果参数minCapacity比数组长度长就进行扩容            grow(minCapacity);    }   //用来扩容的函数    private void grow(int minCapacity) {        int oldCapacity = elementData.length; //获取当前数组长度        int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容当前数组长度的一半 1.8之前是 newCapacity = (oldCapacity * 3)/2+1        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;   //如果新容量还是比指定的minCapacity小就将容量扩充到minCapacity        if (newCapacity - MAX_ARRAY_SIZE > 0) //新容量超过了Integer.MAX_VALUE - 8 可能是Integer.MAX_VALUE            newCapacity = hugeCapacity(minCapacity);         // minCapacity通常是接近size的        elementData = Arrays.copyOf(elementData, newCapacity);    }    //返回的是一个合理的容量值    private static int hugeCapacity(int minCapacity) {        if (minCapacity < 0) // overflow            throw new OutOfMemoryError();        return (minCapacity > MAX_ARRAY_SIZE) ?            Integer.MAX_VALUE :            MAX_ARRAY_SIZE; //Integer.MAX_VALUE - 8    }   //获取ArrayList中元素的个数    public int size() {        return size;    }    //判断是够为空    public boolean isEmpty() {        return size == 0;    }     //判断是否含有某个元素注意这种情况(o==null?e==null:o.equals(e))     //因为ArrayList可以塞进null,所以当o是null的时候只要ArrayList中元素e也是null就返回true     //如果o不是null的话,就是使用equals判断list中是否含有元素o    public boolean contains(Object o) {        return indexOf(o) >= 0;    }     //返回list中元素的下标(第一个),如果存在就返回该元素下标,如果不存在就返回-1    public int indexOf(Object o) {        if (o == null) { //如果元素指定的元素是null            for (int i = 0; i < size; i++)                if (elementData[i]==null)                    return i;        } else { //指定的元素不为null            for (int i = 0; i < size; i++)                if (o.equals(elementData[i])) //循环遍历list 使用eqauls判断list中与指定元素相同的元素                    return i;        }        return -1;    }    //获取最后一个元素o在list中的下标    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--)                //使用equals方法判断相同                if (o.equals(elementData[i]))                    return i;        }        //如果元素不存在返回-1        return -1;    }    //clone方法    public Object clone() {        try {            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);        }    }    //返回数组    public Object[] toArray() {        return Arrays.copyOf(elementData, size);    }   //返回指定index的元素    public E get(int index) {        rangeCheck(index); //index合法性检查        return elementData(index);    }    //根据index对list元素进行赋值    public E set(int index, E element) {        rangeCheck(index); //index越界检查        E oldValue = elementData(index); //返回旧值        elementData[index] = element; //设置新值        return oldValue;    }   //添加指定的元素到list的末尾    public boolean add(E e) {        ensureCapacityInternal(size + 1);  // 确保添加一个元素不会越界 如果是DEFAULTCAPACITY_EMPTY_ELEMENTDATA第一次添加的时候list会扩容到默认的10        elementData[size++] = e;        return true;    }   //在指定index添加元素    public void add(int index, E element) {        rangeCheckForAdd(index); //index越界检测        ensureCapacityInternal(size + 1);  // Increments modCount!!        System.arraycopy(elementData, index, elementData, index + 1,                         size - index);        elementData[index] = element;        size++;    }    //删除指定index的元素并返回原先的元素    public E remove(int index) {        rangeCheck(index); //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; // GC        //返回原先的值        return oldValue;    }    //删除list中出现的第一个元素o    public boolean remove(Object o) {        if (o == null) {            for (int index = 0; index < size; index++)                if (elementData[index] == null) {                    fastRemove(index);                    return true;                }        } else {            for (int index = 0; index < size; index++)            //遍历使用equals判断相等                if (o.equals(elementData[index])) {                    fastRemove(index);                    return true;                }        }        return false;    }    //私有的删除方法,在remove中调用,在这个方法中不包含越界检查和返回原来值    private void fastRemove(int index) {        modCount++;        int numMoved = size - index - 1;        if (numMoved > 0)            System.arraycopy(elementData, index+1, elementData, index,                             numMoved);        elementData[--size] = null; //GC    }    //清空列表    public void clear() {        modCount++;        for (int i = 0; i < size; i++)            elementData[i] = null; //GC        size = 0;    }    //添加Collection中所有的元素到当前的list中    public boolean addAll(Collection<? extends E> c) {        //collection转数组        Object[] a = c.toArray();        //获取数组的长度 即元素的个数        int numNew = a.length;        //确保list内部数组容量        ensureCapacityInternal(size + numNew);  // Increments modCount        //复制数组        System.arraycopy(a, 0, elementData, size, numNew);        //修改list 元素个数        size += numNew;        return numNew != 0;    }    //指定index向list插入Collection的所有元素    public boolean addAll(int index, Collection<? extends E> c) {        rangeCheckForAdd(index); //检查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,                             numMoved);        System.arraycopy(a, 0, elementData, index, numNew);        size += numNew;        return numNew != 0;    }    protected void removeRange(int fromIndex, int toIndex) {        modCount++;        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;        }        size = newSize;    }     //index越界检查,如果不合法抛出一个运行时异常,    private void rangeCheck(int index) {        if (index >= size)            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    }    // add和addAll的越界检查    private void rangeCheckForAdd(int index) {        if (index > size || index < 0)            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    }    //下标越界异常信息    private String outOfBoundsMsg(int index) {        return "Index: "+index+", Size: "+size;    }    //删除Collection中所有的元素    public boolean removeAll(Collection<?> c) {        Objects.requireNonNull(c);        return batchRemove(c, false);    }    public boolean retainAll(Collection<?> c) {        Objects.requireNonNull(c);        return batchRemove(c, true);    }    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;    }}
原创粉丝点击