您的位置:首页 > 编程语言 > Java开发

【Java入门提高篇】Day21 容器类详解(四)ArrayList源码分析

2019-04-10 09:23 260 查看

 今天要介绍的是List接口中最常用的实现类——ArrayList,本篇的源码分析基于JDK8,如果有不一致的地方,可先切换到JDK8后再进行操作。

 

  本篇的内容主要包括这几块:

 

  1.源码结构介绍

 

  2.源代码展示

 

  3.要点说明

 

  4.优缺点说明

 

一、源码结构介绍

  ArrayList的源码跟之前的接口源码比起来,那可就不能同日而语了,一千多行代码,如果直接看的话确实有些费劲,但仔细看看就会发现,其实大致结构是这样的:

 

  其中包含了好四个内部类:

 

     ArrayListSpliterator:ArrayList可分割的迭代器,基于二分法的可分割迭代器,是为了并行遍历元素而设计的一种迭代器,jdk1.8 中的集合框架中的数据结构都默认实现了 spliterator。

 

  Itr:实现Iterator接口的迭代器,为ArrayList进行优化。

 

  ListItr:实现ListIterator接口的迭代器,为ArrayList进行优化。

 

  SubList:实现了AbstractList和RandomAccess接口的子列表。

 

  这四个内部类就占了将近一半的篇幅,足可见其重要性。这四个类中前三个都是跟迭代器有关,最后一个是为了处理局部列表而设计的子列表类。

           

 

二、源代码展示:

  下面是蹩脚翻译讲解版的源码:

 

 

/**

 * ArrayList 是List接口的动态数组实现,实现了List的所有可选操作,并且允许所有元素,包括null。

 * ArrayList 跟Vector差不多,但它不是线程安全的。

 * ArrayList 的容量会根据列表大小自动调整。在添加大量元素之前,可以使用ensureCapacity 方法来保证列表有足够空间存放元素。

 * ArrayList 不是线程安全的,所以如果多条线程将要对其进行结构性改变时(如添加删除元素),需要使用synchronized 进行同步。

 * 如果不存在这样的对象,则需要使用其同步包装类 Collections.synchronizedList

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

 *

 * iterator() 方法将会返回一个listIterator,其中的方法是“fail-fast(快速失败的)”,如果在创建了迭代器之后,在用迭代器遍历一个列表时,

 * 如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。

 * 但fail-fast 的行为是无法得到保证的,不可能对是否出现不同步并发修改做出任何硬性保证。

 * 快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。

 * 因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。

 */

 

public class ArrayList<E> extends AbstractList<E>

        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

{

    private static final long serialVersionUID = 8683452581122892189L;

 

    /**

     * 默认容量

     */

    private static final int DEFAULT_CAPACITY = 10;

 

    /**

     * 空实例共享的空数组

     * todo 为什么要区分 EMPTY_ELEMENTDATA 与 DEFAULTCAPACITY_EMPTY_ELEMENTDATA

     */

    private static final Object[] EMPTY_ELEMENTDATA = {};

 

    /**

     * 默认大小的空实例共享的空数组

     */

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

 

    /**

     * ArrayList的元素存储在其中的数组缓冲区。ArrayList的容量是这个数组缓冲区的长度。

     * 当添加第一个元素时,任何为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空ArrayList的容量

     * 将扩充到默认大小DEFAULT_CAPA 20000 CITY(10)。

     * 设置为非private 是为了方便内部类进行访问

     *

     * todo 内部动态数组的维护

     */

    transient Object[] elementData;

 

    /**

     * 列表中实际存储的元素个数

     *

     * todo size 与 capacity

     */

    private int size;

 

    /**

     * 构造一个指定初始容量的空列表

     */

    public ArrayList(int initialCapacity) {

        if (initialCapacity > 0) {

            this.elementData = new Object[initialCapacity];

        } else if (initialCapacity == 0) {

            this.elementData = EMPTY_ELEMENTDATA;

        } else {

            throw new IllegalArgumentException("Illegal Capacity: "+

                    initialCapacity);

        }

    }

 

    /**

     * 构造一个默认容量的空列表

     */

    public ArrayList() {

        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

    }

 

    /**

     * 构造一个包含集合C中所有元素的列表,存储顺序为集合C迭代器遍历的顺序

     */

    public ArrayList(Collection<? extends E> c) {

        elementData = c.toArray();

        if ((size = elementData.length) != 0) {

            // c.toArray might (incorrectly) not return Object[] (see 6260652)

            if (elementData.getClass() != Object[].class)

                elementData = Arrays.copyOf(elementData, size, Object[].class);

        } else {

            // replace with empty array.

            this.elementData = EMPTY_ELEMENTDATA;

        }

    }

 

    /**

     * 调整容量大小到列表当前元素个数,以节约存储空间

     */

    public void trimToSize() {

        //todo modCount的作用

        modCount++;

        if (size < elementData.length) {

            elementData = (size == 0)

                    ? EMPTY_ELEMENTDATA

                    : Arrays.copyOf(elementData, size);

        }

    }

 

    /**

     * 增加列表容量以确保它至少能容纳指定数量的元素

     *

     * todo 扩容方式

     */

    public void ensureCapacity(int minCapacity) {

        //最小扩容量

        //如果elementData是空数组则最小扩容量为0,否则最小扩容量为10

        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)

                ? 0

                : DEFAULT_CAPACITY;

 

        //如果指定的容量比最小扩容量大,则进行扩容操作

        if (minCapacity > minExpand) {

            ensureExplicitCapacity(minCapacity);

        }

    }

 

    private static int calculateCapacity(Object[] elementData, int minCapacity) {

        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

            return Math.max(DEFAULT_CAPACITY, minCapacity);

        }

        return minCapacity;

    }

 

    private void ensureCapacityInternal(int minCapacity) {

        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

    }

 

    private void ensureExplicitCapacity(int minCapacity) {

        modCount++;

 

        // overflow-conscious code

        if (minCapacity - elementData.length > 0)

            grow(minCapacity);

    }

 

    /**

     * 数组容量最大值(- 8 是因为部分 JVM 需要在数组中存入部分头信息)

     */

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

 

    /**

     * 扩容函数,扩容1.5 倍,扩容后的列表大小在minCapacity与1.5 倍原大小之间取最大值

     */

    private void grow(int minCapacity) {

        // overflow-conscious code

        int oldCapacity = elementData.length;

        // >> 是右移运算符,作用结果是将原数值的二进制数右移指定位数,转换成十进制的效果

        // 就是除以2的指定次方,这里右移一位即除以2

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

    }

 

    private static int hugeCapacity(int minCapacity) {

        if (minCapacity < 0) // overflow

            throw new OutOfMemoryError();

        return (minCapacity > MAX_ARRAY_SIZE) ?

                Integer.MAX_VALUE :

                MAX_ARRAY_SIZE;

    }

 

    /**

     * 元素个数

     */

    public int size() {

        return size;

    }

 

    /**

     * 是否为空

     */

    public boolean isEmpty() {

        return size == 0;

    }

 

    /**

     * 是否包含某个元素

     */

    public boolean contains(Object o) {

        return indexOf(o) >= 0;

    }

 

    /**

     * 查找元素第一次出现的位置

     */

    public int indexOf(Object o) {

        if (o == null) {

            for (int i = 0; i < size; i++)

                if (elementData[i]==null)

                    return i;

        } else {

            for (int i = 0; i < size; i++)

                if (o.equals(elementData[i]))

                    return i;

        }

        return -1;

    }

 

    /**

     * 查找元素最后一次出现的位置

     */

    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--)

                if (o.equals(elementData[i]))

                    return i;

        }

        return -1;

    }

 

    /**

     * 返回一个深克隆对象

     */

    public Object clone() {

        try {

            // Object 的克隆方法,复制本对象及其内所有基本类型成员和 String 类型成员

            // 但不会复制引用对象

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

    }

 

    /**

     * 将列表转存到数组a中,如果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;

    }

 

    // 位置访问操作

 

 

    @SuppressWarnings("unchecked")

    E elementData(int index) {

        return (E) elementData[index];

    }

 

    /**

     * 取序号为index的元素

     */

    public E get(int index) {

        rangeCheck(index);

 

        return elementData(index);

    }

 

    /**

     * 替换指定位置的元素,并返回原来的元素

     */

    public E set(int index, E element) {

        rangeCheck(index);

 

        E oldValue = elementData(index);

        elementData[index] = element;

        return oldValue;

    }

 

    /**

     * 添加元素

     */

    public boolean add(E e) {

        ensureCapacityInternal(size + 1);  // Increments modCount!!

        elementData[size++] = e;

        return true;

    }

 

    /**

     * 插入元素

     */

    public void add(int index, E element) {

        rangeCheckForAdd(index);

 

        ensureCapacityInternal(size + 1);  // Increments modCount!!

        System.arraycopy(elementData, index, elementData, index + 1,

                size - index);

        elementData[index] = element;

        size++;

    }    

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: