Java容器 ArrayList源码分析

1 ArrayList 中的基本方法实现

ArrayList 方法签名

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

RandomAccess接口说明ArrayList可随机访问的。继承自AbstractList

ArrayList中的实例域:

    private static final int DEFAULT_CAPACITY = 10;
    transient Object[] elementData; // non-private to simplify nested class access
    private int size;

elementData 数组用于保存数据
DEFAULT_CAPACITY 没有指定数组长度时的默认数组容量
size表示数组中真正包含的元素,size<=capacity

随机读取的实现 get

  public E get(int index) {
        // 数组范围检查
        rangeCheck(index);
        //实际上就是对数组elementData[index]的访问
        return elementData(index);
    }
    //范围检查,并没有对index < 0 进行检查。用的是数组访问的负数越界异常java.lang.ArrayIndexOutOfBoundsException
   private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

  @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

get() 首先checkRange, 此时没有对index是负数的检查。访问数组index<0,会抛出ArrayIndexOutOfBoundsException的错误。范围检查之后,直接elementDate[index]返回元素
get(index)的时间复杂度为 O(1), 这是ArrayList的优势

add

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

   private void ensureCapacityInternal(int minCapacity) {
       // DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组缓存,实例化空数组时无需每次都new一个数组,第一次添加时new一个新的数组。用于提升性能。
        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)
            //当需要的最小的容量比数组的length大时,进行扩容
            grow(minCapacity);
    }

add(E e),首先需要进行容量检查 & modCount + 1,如果是DEFAULTCAPACITY_EMPTY_ELEMENTDATA需要分配新的数组。如果添加后的size超过当前的容量,需要扩容。添加则是 elementData[size++] = e;

     public void add(int index, E element) {
         // 范围检查
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //在某个位置上插入需要数组的copy,此时会有性能消耗
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }
    //rangeCheck
     private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

add(int index, E element):checkRange, copyOf array, add。该添加方法性能消耗在copy array上。
add的最好的情况(在数组末尾添加)时间复杂度为O(1), 最坏的情况下(在数组首添加)时间复杂度为O(n)。

扩容

     private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            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);
    }

grow(),新的数组的长度是原来的1.5倍。再用Arrays.copyOf将旧的数组复制到新的数组中。

remove

     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;
    }

    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++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

     /*
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     */
    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; // clear to let GC do its work
    }

用index remove,先进行rangeCheck, 然后通过将index+1及后面的元素复制到index位置上,index就被删除了。
用object remove, 使用fastRemove。fastRemove是没有rangeCheck, 也不放回删除的元素的删除方法,也是通过数组的copy实现Index位置上元素的覆盖。
remove方法中都需要数组复制,所以性能上有消耗。

2 ArrayList 的迭代器
 public Iterator<E> iterator() {
        return new Itr();
    }

ArrayList中返回的迭代器是Itr的实例。Itr是ArrayList的内部类,继承自Iterator,实现了基本的迭代器方法

 private class Itr implements Iterator<E> {}
    private class Itr implements Iterator<E> {
        // 下一个元素的索引
        int cursor;       // index of next element to return
        // 操作的最后一个元素的索引
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
        //下一个元素的索引 != size,表示还有下一个元素
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            //确认迭代器操作过程中没有对list上有structural modification
            checkForComodification();
            //当前要操作的index
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            //返回当前index上的元素
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                //调用的是ArrayList上的remove操作
                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();
        }
    }

ArrayList中还有一个ListIterator。

    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

ListItr是ArrayList的内部迭代器实现。ListIterator是一个双向的迭代器,有previous(),next()等操作

  /**
     * An optimized version of AbstractList.ListItr
     */
    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor - 1;
        }

        @SuppressWarnings("unchecked")
        public E previous() {
            checkForComodification();
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.set(lastRet, e);
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

ListItr继承自Itr。除了向后访问的方法之外。还添加了向前访问,以及add,set操作。

3. sublist
     public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

ArrayList.sublist 操作实际上返回的是SubList实例。SubList是ArrayList的内部类,实际上生成的sublist指向的List还是原来的列表。也就是说,对于sublist的操作都会反应在原来的List对象上,并不会生成一个新的sub list。

         public E set(int index, E e) {
            rangeCheck(index);
            checkForComodification();
            E oldValue = ArrayList.this.elementData(offset + index);
            //实际上都是对于ArrayList的elementData上的操作
            ArrayList.this.elementData[offset + index] = e;
            return oldValue;
        }

        public E get(int index) {
            rangeCheck(index);
            checkForComodification();
            //实际上都是对于ArrayList的elementData上的操作
            return ArrayList.this.elementData(offset + index);
        }
4. ArrayList 总结

ArrayList 是列表的数组实现,可随机访问(通过数组的直接寻址)。
ArrayList 访问效率高,但是对于添加和删除的效率低。所以不利于有大量添加和删除业务的容器。此时需要用LinkedList作为容器。
ArrayList中有双向访问的迭代器(ListIterator)实现,可以双向访问,并且可以在迭代器访问时添加和删除。
ArrayList中的子列表本质上指向的是原来的列表,所以对于子列表的操作会反应到原来的列表中。

4. ArrayList & Vector
  1. ArrayList 的方法都不是同步的,所以在多线程中对同一个ArrayList操作需要额外的同步工作。Vector中已经做了同步,无需再有额外的同步机制
  2. ArrayList 的扩容是原来的1.5倍,添加了50%的空间。Vector 通过capacityIncrement开控制容量的增长量的,默认情况下是增加100%的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值