ArrayList 源码分析

ArrayList

ArrayList 能解决什么问题?什么时候使用 ArrayList?

1)ArrayList 底层存储结构是一个对象数组,因此只能存储 Java 对象和 null 值。
2)每个 ArrayList 都有一个容量,容量表示该 ArrayList 当前能容纳的元素个数,
随着元素的增加,ArrayList 会自动扩容,扩容操作通过 System.arraycopy 完成旧元素的拷贝,
因此 ArrayList 适用于元素个数不确定的对象集合。
3)ArrayList 不是线程安全的,多线程并发读写 ArrayList 并且至少有一个线程修改了它的结构【增加、删除元素、扩容等】,
则 ArrayList 将抛出 ConcurrentModificationException 异常。
4)ArrayList 的 size、isEmpty、get、set、iterator 和 listIterator 方法以常量时间运行,其他的操作基本以线性时间运行。
5)ArrayList 实现了 RandomAccess 接口,随机读写以常量时间运行,效率高。
6)ArrayList 的快速失败机制【fast-fail】:iterator 和 listIterator 返回的迭代器是快速失败的,
如果不是通过 ListIterator#remove() 或 ListIterator#add(Object) 方法修改其结构,
则 ArrayList 将尽最大努力抛出 ConcurrentModificationException 异常。
7)ArrayList 的缩容机制:通过 trimToSize 方法将 ArrayList 的容量缩小为当前元素的个数,以减少 ArrayList 的内存占用。
8)ArrayList 的扩容机制:默认为 1.5 倍向下取整扩容,如果批量添加元素,则以 size+newNum 进行扩容。

如何使用 ArrayList?

1)在创建 ArrayList 时可以指定一个合适的初始化容量,以减少频繁扩容带来的性能损耗,使用默认容量值 10 或指定容量值。
2)对于 ArrayList 类型的静态只读属性,通过 trimToSize 方法将 ArrayList 的容量缩小为当前元素的个数,以减少 ArrayList 的内存占用。
3)ArrayList 的随机删除操作会导致部分元素往左 shift,随机删除操作越多,内存拷贝越频繁,性能越差。

使用 ArrayList 有什么风险?

1)ArrayList 的最大容量为 Integer.MAX_VALUE,使用不当可能会导致内存溢出。
2)ArrayList 不是线程安全的,ArrayList 作为共享资源在多线程下执行写操作时,会出现元素丢失的问题。

ArrayList 核心操作的实现原理?

  • 属性说明
    /**
     * 通过无参构造函数创建 ArrayList 实例时,第一次扩容的默认容量值。
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 通过带容量构造函数创建 ArrayList 实例时,用于共享的空数组对象
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * 通过无参构造函数创建 ArrayList 实例时,用于共享的空数组对象
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * ArrayList 底层存储元素的对象数组,数组的长度就是 ArrayList 的容量
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * ArrayList 包含元素的个数
     */
    private int size;
  • 创建实例
    /**
     * 创建一个初始化容量为 10 的空 ArrayList 实例
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 创建一个指定初始容量的空 ArrayList 实例
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 指定容量为负数时抛出 IllegalArgumentException 异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                    initialCapacity);
        }
    }

    /**
     * 创建一个包含指定集合中所有元素的 ArrayList 实例,集合中的元素按照迭代器顺序返回。
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        // 形参集合非空
        if ((size = elementData.length) != 0) {
            if (elementData.getClass() != Object[].class) {
                elementData = Arrays.copyOf(elementData, size, Object[].class);
            }
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
  • 在尾部添加元素
    /**
     * 将指定的元素添加到列表的尾部
     */
    @Override
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

    /**
     * This helper method split out from add(E) to keep method
     * bytecode size under 35 (the -XX:MaxInlineSize default value),
     * which helps when add(E) is called in a C1-compiled loop.
     */
    private void add(E e, Object[] elementData, int s) {
        // 当前元素的个数已经达到底层数组的最大容量,需要进行扩容
        if (s == elementData.length) {
            elementData = grow();
        }
        // 存储元素
        elementData[s] = e;
        // 递增元素个数
        size = s + 1;
    }

    private Object[] grow() {
        return grow(size + 1);
    }

    /**
     * 增加 ArrayList 的容量,以保证其至少能够容纳 minCapacity 个元素
     */
    private Object[] grow(int minCapacity) {
        return elementData = Arrays.copyOf(elementData,
                newCapacity(minCapacity));
    }

    private int newCapacity(int minCapacity) {
        // 获取旧容量
        final int oldCapacity = elementData.length;
        // 计算新容量(1.5 倍向下取整)
        final int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity <= 0) {
            // 如果是通过无参构造函数创建的实例,且是第一次添加元素
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                // 单个添加则返回默认初始容量 10,批量添加并且元素个数大于 10,则返回目标元素个数 minCapacity
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            }
            if (minCapacity < 0) {
                throw new OutOfMemoryError();
            }
            // 通过 addAll 批量添加元素,并且个数超出(剩余容量+原始容量*0.5),则返回目标容量
            return minCapacity;
        }
        // 新容量小于 Integer.MAX_VALUE - 8,则返回 1.5 倍向下取整的值
        return newCapacity - MAX_ARRAY_SIZE <= 0
                ? newCapacity
                        : ArrayList.hugeCapacity(minCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        // 目标容量溢出
        if (minCapacity < 0) {
            throw new OutOfMemoryError();
        }
        // 新容量等于 Integer.MAX_VALUE - 8,则返回该值,否则返回 Integer.MAX_VALUE
        return minCapacity > MAX_ARRAY_SIZE
                ? Integer.MAX_VALUE
                        : MAX_ARRAY_SIZE;
    }
  • 在尾部批量添加元素
    /**
     * 将形参集合中的所有元素顺序添加到 ArrayList 的尾部
     */
    @Override
    public boolean addAll(Collection<? extends E> c) {
        final Object[] a = c.toArray();
        // 增加结构化修改计数值,在并发修改时可抛出 CME
        modCount++;
        // 形参集合为空时直接返回
        final int numNew = a.length;
        if (numNew == 0) {
            return false;
        }
        Object[] elementData;
        final int s;
        // 新增元素个数大于 ArrayList 剩余可用容量时执行扩容操作
        if (numNew > (elementData = this.elementData).length - (s = size)) {
            elementData = grow(s + numNew);
        }
        // 拷贝目标元素到底层数组中
        System.arraycopy(a, 0, elementData, s, numNew);
        // 增加元素个数
        size = s + numNew;
        return true;
    }
  • 读取元素
    /**
     * 获取 ArrayList 指定索引处的元素
     */
    @Override
    public E get(int index) {
        // 索引合法性校验
        Objects.checkIndex(index, size);
        return elementData(index);
    }

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        // 获取底层数组指定索引的元素
        return (E) elementData[index];
    }
  • 替换元素
    /**
     * 替换指定索引处的元素,并返回旧值
     */
    @Override
    public E set(int index, E element) {
        Objects.checkIndex(index, size);
        // 读取旧值
        final E oldValue = elementData(index);
        // 设置新值
        elementData[index] = element;
        // 返回旧值
        return oldValue;
    }
  • 移除指定索引处的元素
    /**
     * 移除指定索引处的元素
     */
    @Override
    public E remove(int index) {
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked")
        final E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

    /**
     * 忽略下标校验,并且无返回值的快速元素移除
     */
    private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        // 被移除元素不是最后一个元素
        if ((newSize = size - 1) > i) {
            // 目标索引之后的元素集体左移
            System.arraycopy(es, i + 1, es, i, newSize - i);
        }
        // 将最后一个元素置为 null,并修改总元素个数
        es[size = newSize] = null;
    }
  • 移除第一个匹配的元素
    /**
     * 从 ArrayList 中移除第一个匹配形参的元素,通过  Objects.equals(o, get(i)) 进行相等性比较
     */
    @Override
    public boolean remove(Object o) {
        final Object[] es = elementData;
        final int size = this.size;
        int i = 0;
        // 查找目标元素的下标
        found: {
            if (o == null) {
                for (; i < size; i++) {
                    if (es[i] == null) {
                        break found;
                    }
                }
            } else {
                for (; i < size; i++) {
                    if (o.equals(es[i])) {
                        break found;
                    }
                }
            }
            return false;
        }
        // 快速移除
        fastRemove(es, i);
        return true;
    }
  • 批量移除元素
    /**
     * 从 ArrayList 中移除包含在形参集合中的所有元素
     */
    @Override
    public boolean removeAll(Collection<?> c) {
        return batchRemove(c, false, 0, size);
    }

    /**
     * created by ZXD at 19 Nov 2018 T 21:24:42
     * @param c 目标集合
     * @param complement 是否取补集
     * @param from 起始索引,包含
     * @param end 结束索引,不包含
     * @return
     */
    boolean batchRemove(Collection<?> c, boolean complement,
            final int from, final int end) {
        Objects.requireNonNull(c);
        final Object[] es = elementData;
        int r;
        // Optimize for initial run of survivors
        // 查找到需要移除的第一个元素的下标
        for (r = from;; r++) {
            // 如果未找到则直接返回 false
            if (r == end) {
                return false;
            }
            if (c.contains(es[r]) != complement) {
                break;
            }
        }
        // 需要填充的第一个元素的下标【原来的元素被移除】
        int w = r++;
        try {
            for (Object e; r < end; r++) {
                if (c.contains(e = es[r]) == complement) {
                    // 需要保留的元素按顺序进行填充
                    es[w++] = e;
                }
            }
        } catch (final Throwable ex) {
            // 将结束索引后的元素集体左移进行填充
            System.arraycopy(es, r, es, w, end - r);
            w += end - r;
            throw ex;
        } finally {
            modCount += end - w;
            // 整体移动元素填充空隙,并将索引为 size-1 之后的元素置为 null
            shiftTailOverGap(es, w, end);
        }
        return true;
    }
  • 按条件移除
    /**
     * 从 ArrayList 中移除满足函数式断言的所有元素
     */
    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        return removeIf(filter, 0, size);
    }

    /**
     * Removes all elements satisfying the given predicate, from index
     * i (inclusive) to index end (exclusive).
     */
    boolean removeIf(Predicate<? super E> filter, int i, final int end) {
        Objects.requireNonNull(filter);
        int expectedModCount = modCount;
        final Object[] es = elementData;
        // Optimize for initial run of survivors
        for (; i < end && !filter.test(ArrayList.elementAt(es, i)); i++) {
            ;
        }
        // 首先查找所有需要移除的元素索引,之后进行物理删除
        if (i < end) {
            final int beg = i;
            final long[] deathRow = ArrayList.nBits(end - beg);
            deathRow[0] = 1L;   // set bit 0
            for (i = beg + 1; i < end; i++) {
                // 如果满足函数式断言
                if (filter.test(ArrayList.elementAt(es, i))) {
                    // 记录需要删除元素的下标
                    ArrayList.setBit(deathRow, i - beg);
                }
            }
            // 标记过程中出现多线程并发修改,则抛出 ConcurrentModificationException
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            expectedModCount++;
            modCount++;
            int w = beg;
            for (i = beg; i < end; i++) {
                // 从第一个被删除的位置开始,将需要保留的元素顺序进行填充
                if (ArrayList.isClear(deathRow, i - beg)) {
                    es[w++] = es[i];
                }
            }
            shiftTailOverGap(es, w, end);
            return true;
        } else {
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            return false;
        }
    }
  • 读取目标元素第一次出现的索引
    /**
     * 形参对象在 ArrayList 中第一次出现的索引,如果不存在相等的元素,则返回 -1
     */
    @Override
    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;
    }
  • 读取目标元素最后一次出现的索引
    /**
     * 形参对象在 ArrayList 中最后一次出现的索引,如果不存在相等的元素,则返回 -1
     */
    @Override
    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;
    }
  • 目标元素是否包含在列表中
    @Override
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
  • 交集
    /**
     * 移除 ArrayList 中不包含在形参集合中的所有元素
     */
    @Override
    public boolean retainAll(Collection<?> c) {
        return batchRemove(c, true, 0, size);
    }
  • 逐个替换
    /**
     * 通过函数式接口将 ArrayList 中的元素进行逐个替换
     * created by ZXD at 19 Nov 2018 T 21:51:23
     * @param operator
     */
    @Override
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        final int size = this.size;
        for (int i = 0; modCount == expectedModCount && i < size; i++) {
            // 将当前元素进行替换
            es[i] = operator.apply(ArrayList.elementAt(es, i));
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
  • 通过指定的比较器对 ArrayList 中的元素进行排序
    @Override
    @SuppressWarnings("unchecked")
    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++;
    }
  • 迭代遍历
    /**
     * 顺序迭代 ArrayList 中所有元素的简单迭代器
     */
    @Override
    public Iterator<E> iterator() {
        return new Itr();
    }

    /** 
     * 顺序迭代 ArrayList 中所有元素的列表迭代器,支持的操作更丰富
     */
    @Override
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    /**
     * 通过函数式接口顺序消费 ArrayList 中的每个元素
     */
    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        final int size = this.size;
        for (int i = 0; modCount == expectedModCount && i < size; i++) {
            action.accept(ArrayList.elementAt(es, i));
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
  • 返回包含 ArrayList 所有元素的对象数组
    /**
     * 返回包含 ArrayList 所有元素的对象数组
     */
    @Override
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    /**
     * 返回包含 ArrayList 所有元素的对象数组,可指定返回类型
     */
    @Override
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // 形参数组的长度小于元素个数
        if (a.length < size) {
            // 拷贝 ArrayList 中的所有元素
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        }
        // 拷贝 ArrayList 中的所有元素
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size) {
            a[size] = null;
        }
        return a;
    }
  • 元素总数
    /**
     * 返回 ArrayList 中的元素个数
     */
    @Override
    public int size() {
        return size;
    }
  • 是否为空
    /**
     * ArrayList为空时返回true
     */
    @Override
    public boolean isEmpty() {
        return size == 0;
    }
  • 扩容过程
    /**
     * 增加 ArrayList 的容量以至少能够容纳 minCapacity 个元素
     */
    public void ensureCapacity(int minCapacity) {
        // 通过无参构造函数创建,并且 minCapacity<=10 时不会执行扩容操作
        if (minCapacity > elementData.length
                && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                && minCapacity <= DEFAULT_CAPACITY)) {
            modCount++;
            grow(minCapacity);
        }
    }
  • 缩容
    /**
     * 将容量缩小为 ArrayList 中元素的个数,以节约内存使用
     */
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            /**
             * ArrayList 为空时,底层数组修改为 EMPTY_ELEMENTDATA
             * ArrayList 非空时,通过数组拷贝完成
             */
            elementData = size == 0
                    ? EMPTY_ELEMENTDATA
                            : Arrays.copyOf(elementData, size);
        }
    }
  • 清空 ArrayList
    /**
     * 移除 ArrayList 中的所有元素,个数置为0,容量保持不变
     */
    @Override
    public void clear() {
        modCount++;
        final Object[] es = elementData;
        for (int to = size, i = size = 0; i < to; i++) {
            es[i] = null;
        }
    }
原文地址:https://www.cnblogs.com/zhuxudong/p/9581072.html