ArrayList源码分析总结

1,ArrayList简介

     ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访  问。稍后,我们会比较List的“快速随机访问”和“通过Iterator迭代器访问”的效率。ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输,和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。

 2,设计原理

   (01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10。
   (02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。
   (03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。

   (04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

3,源码分析

     1,构造方法
      // 默认构造函数   ArrayList()
      // capacity是ArrayList的默认容量大小。当由于增加数据导致容量不足时,容量会添加上一次容量大小的一半。
      ArrayList(int capacity)
      // 创建一个包含collection的ArrayList
      ArrayList(Collection<? extends E> collection)
      2,成员变量
         ArrayList包含了两个重要的对象:elementData 和 size。
      (01) elementData 是"Object[]类型的数组",它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数 ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10。elementData数组的大小会根据ArrayList容量的增长而动态的增长,具体的增长方式,请参考源码分析中的ensureCapacity()函数。
      (02) size 则是动态数组的实际大小。
    3,  方法  
         这里只介绍一个常用的方法:
     3.1 add方法
      public boolean add(E e) {
        //往数组添加元素前,先检查数组容量够不够
        ensureCapacityInternal(size + 1);  
        //将元素添加到数组对应的位置上去
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        //如果为空数组,则minCapacity取minCapacity和10的最大值,默认数组中存放10个元素
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }
        //是否需要扩容判断
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        //如果元素个数大于数组长度时,则需扩容
        if (minCapacity - elementData.length > 0)
            //扩容
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        // 原数组长度
        int oldCapacity = elementData.length;
        //新数组长度 = 原数组长度 + 原数组长度的一半       也就是原数组长度的1.5倍
        // 运算符 >> 是带符号右移. 如 oldCapacity = 10,则 newCapacity = 10 + (10 >> 1) = 10 + 5 = 15
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //如果扩容1.5倍后还不够,则新数组长度等于当前元素的个数
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 若 newCapacity 大于最大存储容量,则进行大容量分配,数组容量分配了Integer的最大值
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //最后调用Arrays.copyOf将数组进行克隆,得到一个新的容量的数组
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    //Arrays数组工具类的copyOf方法:original参数为元素组,newLength参数为新数组大小
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
    public static byte[] copyOf(byte[] original, int newLength) {
        byte[] copy = new byte[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
    //jdk1.0 System的arraycopy方法是一个本地方法,底层是用C或C++语言实现,这里就不说了
    public static native void arraycopy(Object src,  int  srcPos,
        Object dest, int destPos,int length);
    3.2 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; // clear to let GC do its work
    }
    5.3 sort方法
     //ArrayList中也有排序的方法,给sort方法传一个自定义的比较器(实现comparator接口)或者元素自身是一个比较器(实现comparable接口)
     public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
    3.4 subList方法
     public List<E> subList(int fromIndex, int toIndex) {
        //参数检查
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }
    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0) //起始下标不能为空
          throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > size) //末尾下标不能大于数组长度
          throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)//起始下标不能大于末尾下标
          throw new IllegalArgumentException("fromIndex(" + fromIndex +") > toIndex(" + toIndex +")");
    }
    private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;
        private final int parentOffset;
        private final int offset;
        int size;
        //parent为new SubList(this, 0, fromIndex, toIndex)中的this对象
        //parent也就是到截取的数组对象
        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;
        }
        这个子类中也定义了自己的一些方法,这里没有列举出
    }
 

猜你喜欢

转载自blog.csdn.net/weixin_39352976/article/details/79990982