为了账号安全,请及时绑定邮箱和手机立即绑定

ArrayList 源码分析

标签:
Java

13)从头开始遍历元素,返回第一个和目标元素相等的元素索引,如果不存在,则返回 -1。

    /**
     * 从头开始遍历元素,返回第一个和目标元素相等的元素索引,如果不存在,则返回 -1
     */
    @Override
    public int indexOf(Object o) {        /**
         * 返回第一个匹配元素的索引
         */
        if (o == null) {            for (int i = 0; i < this.size; i++) {                if (this.elementData[i]==null) {                    return i;
                }
            }
        } else {            for (int i = 0; i < this.size; i++) {                if (o.equals(this.elementData[i])) {                    return i;
                }
            }
        }        return -1;
    }

14)从尾部开始遍历元素,返回第一个和目标元素相等的元素索引,如果不存在,则返回 -1。

    /**
            * 从尾部开始遍历元素,返回第一个和目标元素相等的元素索引,如果不存在,则返回 -1
     */
    @Override
    public int lastIndexOf(Object o) {        /**
         * 返回第一个匹配元素的索引
         */
        if (o == null) {            for (int i = this.size-1; i >= 0; i--) {                if (this.elementData[i]==null) {                    return i;
                }
            }
        } else {            for (int i = this.size-1; i >= 0; i--) {                if (o.equals(this.elementData[i])) {                    return i;
                }
            }
        }        return -1;
    }

15)ArrayList 中是否包含和目标元素相等的元素,如果包含,则返回 true;否则返回 false。

    /**
            * 从头开始遍历,并通过 {@link Object#equals(Object)} 方法获取相等元素的索引
     */
    @Override
    public boolean contains(Object o) {        return this.indexOf(o) >= 0;
    }

16)ArrayList 中当前元素的个数

    /**
     * 当前元素个数
     * created by ZXD at 15 Jul 2018 T 11:25:21
     * @return
     */
    @Override
    public int size() {        return this.size;
    }

17)ArrayList 是否为空

    /**
          * 是否为空
     * created by ZXD at 15 Jul 2018 T 11:25:48
     * @return
     */
    @Override
    public boolean isEmpty() {        return this.size == 0;
    }

18)将 ArrayList 的容量缩小为当前元素的个数,以减少 ArrayList 的内存占用,适合于静态 ArrayList 实例。

    /**
        *  将 ArrayList 的容量缩小为当前元素的个数,以减少 ArrayList 的内存占用。
     */
    public void trimToSize() {        // 结构修改计数器
        modCount++;        /**
         * 当元素个数小于对象数组长度时,缩小其容量为元素个数,降低 ArrayList 的内存占用。
         */
        if (this.size < this.elementData.length) {            this.elementData = this.size == 0
                    ? ArrayList.EMPTY_ELEMENTDATA
                            : Arrays.copyOf(this.elementData, this.size);
        }
    }

19)如果需要,则增加 ArrayList 的容量以满足最少能容纳 minCapacity 个元素。

    /**
     * 增加 ArrayList 的容量以满足最少能容纳 minCapacity 个元素
     */
    public void ensureCapacity(int minCapacity) {        /**
         * 预期容量大于可用容量时执行扩容操作
         */
        if (minCapacity > this.elementData.length
                && !(this.elementData == ArrayList.DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                && minCapacity <= ArrayList.DEFAULT_CAPACITY)) {
            modCount++;            this.grow(minCapacity);
        }
    }

20)将 ArrayList 转换为指定类型的对象数组,包含所有元素。

    @Override
    @SuppressWarnings("unchecked")    public <T> T[] toArray(T[] a) {        /**
         * 形参数组的长度小于 ArrayList 的 size,则默认复制 ArrayList 的所有元素,
         * 长度为 ArrayList 的 size。
         */
        if (a.length < this.size) {            return (T[]) Arrays.copyOf(this.elementData, this.size, a.getClass());
        }
        System.arraycopy(this.elementData, 0, a, 0, this.size);        /**
         * 复制 ArrayList 的所有元素,并将索引为 size 的元素设置为 null,返回新数组
         */
        if (a.length > this.size) {
            a[this.size] = null;
        }        return a;
    }

21)将 ArrayList 实例转换为 Object 对象数组

    /**
     * 返回包含 ArrayList 所有元素的对象数组
     */
    @Override
    public Object[] toArray() {        // 拷贝出 ArrayList 中存储在底层对象数组中的所有元素
        return Arrays.copyOf(this.elementData, this.size);
    }

22)使用函数式接口顺序消费 ArrayList 中的每个元素,出现并发修改时,之前消费的元素不能回滚

    /**
     * 顺序消费 ArrayList 中的每个元素
     */
    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);        // 缓存并发修改计数值
        final int expectedModCount = modCount;        // 读取底层对象数组
        final Object[] es = this.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();
        }
    }

23)移除 ArrayList 中满足指定函数式断言的所有元素

    /**
     * 移除 ArrayList 中满足指定函数式断言的所有元素
     */
    @Override
    public boolean removeIf(Predicate<? super E> filter) {        return this.removeIf(filter, 0, this.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 = this.elementData;        /**
         *  从头开始略过不满足断言的元素,找到第一个需要移除的元素索引
         */
        for (; i < end && !filter.test(ArrayList.elementAt(es, i)); i++) {
            ;
        }        // Tolerate predicates that reentrantly access the collection for
        // read (but writers still get CME), so traverse once to find
        // elements to delete, a second pass to physically expunge.
        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);
                }
            }            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];
                }
            }            this.shiftTailOverGap(es, w, end);            return true;
        } else {            if (modCount != expectedModCount) {                throw new ConcurrentModificationException();
            }            return false;
        }
    }

24)将 ArrayList 中的所有元素替换为通过二元函数式接口变换后的值,元素类型保持不变。

    /**
     * UnaryOperator 接受类型为 E 的参数并返回类型为 E 的对象
     */
    @Override
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);        final int expectedModCount = modCount;        final Object[] es = this.elementData;        final int size = this.size;        for (int i = 0; modCount == expectedModCount && i < size; i++) {            // 遍历并替换 ArrayList 中的每个元素
            es[i] = operator.apply(ArrayList.elementAt(es, i));
        }        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();
        }
        modCount++;
    }

25)通过指定的比较器对 ArrayList 中的元素执行排序

    /**
     * 对 ArrayList 进行排序
     */
    @Override
    @SuppressWarnings("unchecked")    public void sort(Comparator<? super E> c) {        final int expectedModCount = modCount;        // 对对象数组内指定范围的元素执行排序
        Arrays.sort((E[]) this.elementData, 0, this.size, c);        if (modCount != expectedModCount) {            throw new ConcurrentModificationException();
        }
        modCount++;
    }

26)返回 ArrayList 的顺序迭代器

    /**
     * 返回 ArrayList 的顺序迭代器
     */
    @Override
    public Iterator<E> iterator() {        return new Itr();
    }    /**
     * An optimized version of AbstractList.Itr
     * 只能往后遍历,支持移除元素
     */
    private class Itr implements Iterator<E> {        int cursor;       // 下一个返回元素的索引,从 0 开始
        int lastRet = -1; // 最近一个返回元素的索引
        int expectedModCount = ArrayList.this.modCount; // fast-fail 机制的计数器

        Itr() {}        /**
         * 是否还有下一个元素
         * created by ZXD at 15 Jul 2018 T 11:39:55
         * @return
         */
        @Override
        public boolean hasNext() {            return this.cursor != ArrayList.this.size;
        }        /**
         * 获取下一个元素
         * created by ZXD at 15 Jul 2018 T 11:40:12
         * @return
         */
        @Override
        @SuppressWarnings("unchecked")        public E next() {            /**
             * 并发修改校验,创建迭代器时会获取外部修改计数器值并将其缓存,
             * 通过比较缓存值和外部计数器值来判断是否发生并发结构修改。
             */
            this.checkForComodification();            // 获取下一个元素的索引
            final int i = this.cursor;            // 元素已经全部遍历完成,并发遍历时其中有线程删除了元素时可能出现
            if (i >= ArrayList.this.size) {                throw new NoSuchElementException();
            }            final Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length) {                throw new ConcurrentModificationException();
            }            // 递增游标值
            this.cursor = i + 1;            // 返回目标值
            return (E) elementData[this.lastRet = i];
        }        @Override
        public void remove() {            if (this.lastRet < 0) {                throw new IllegalStateException();
            }            this.checkForComodification();            try {                // 移除 ArrayList 中的元素
                ArrayList.this.remove(this.lastRet);                // 更新游标值
                this.cursor = this.lastRet;                // 移除元素时,lastRet 置为 -1
                this.lastRet = -1;                // 更新内部的并发修改计数值
                this.expectedModCount = ArrayList.this.modCount;
            } catch (final IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();
            }
        }        /**
         * 顺序消费未迭代的所有元素
         * created by ZXD at 15 Jul 2018 T 11:44:41
         * @param action
         */
        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);            final int size = ArrayList.this.size;            int i = this.cursor;            if (i < size) {                final Object[] es = ArrayList.this.elementData;                if (i >= es.length) {                    throw new ConcurrentModificationException();
                }                // 游标值小于 size 并且未发生并发结构修改
                for (; i < size && ArrayList.this.modCount == this.expectedModCount; i++) {                    // 使用函数式接口消费目标元素
                    action.accept(ArrayList.elementAt(es, i));
                }                // update once at end to reduce heap write traffic
                // 更新游标值
                this.cursor = i;                this.lastRet = i - 1;                this.checkForComodification();
            }
        }        final void checkForComodification() {            /**
             * 判断是否存在多线程并发修改 ArrayList 实例
             */
            if (ArrayList.this.modCount != this.expectedModCount) {                throw new ConcurrentModificationException();
            }
        }
    }

27)返回 ArrayList 的列表迭代器

    /**
     * 返回 ArrayList 的列表迭代器
     */
    @Override
    public ListIterator<E> listIterator() {        return new ListItr(0);
    }    /**
     * An optimized version of AbstractList.ListItr
     * 支持向前或向后遍历,支持在迭代过程中增加、移除、修改元素
     */
    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {            super();
            cursor = index;
        }        /**
         * 是否存在可迭代的前一个元素
         * created by ZXD at 15 Jul 2018 T 11:47:17
         * @return
         */
        @Override
        public boolean hasPrevious() {            return cursor != 0;
        }        /**
         * 获取下一个迭代元素的索引
         * created by ZXD at 15 Jul 2018 T 11:47:45
         * @return
         */
        @Override
        public int nextIndex() {            return cursor;
        }        /**
         * 获取前一个迭代元素的索引
         * created by ZXD at 15 Jul 2018 T 11:48:02
         * @return
         */
        @Override
        public int previousIndex() {            return cursor - 1;
        }        /**
         * 获取前一个迭代元素
         * created by ZXD at 15 Jul 2018 T 11:48:20
         * @return
         */
        @Override
        @SuppressWarnings("unchecked")        public E previous() {
            checkForComodification();            final int i = cursor - 1;            if (i < 0) {                throw new NoSuchElementException();
            }            final Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length) {                throw new ConcurrentModificationException();
            }            // 更新游标并返回目标元素
            cursor = i;            return (E) elementData[lastRet = i];
        }        /**
         * 更新最后一次返回的元素
         * created by ZXD at 15 Jul 2018 T 11:49:59
         * @param e
         */
        @Override
        public void set(E e) {            if (lastRet < 0) {                throw new IllegalStateException();
            }
            checkForComodification();            try {
                ArrayList.this.set(lastRet, e);
            } catch (final IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();
            }
        }        /**
         * 迭代过程中动态将元素插入到下一次迭代的索引处
         * created by ZXD at 15 Jul 2018 T 11:50:25
         * @param e
         */
        @Override
        public void add(E e) {
            checkForComodification();            try {                final int i = cursor;
                ArrayList.this.add(i, e);                // 更新游标、最后一次返回的元素下标、结构修改计数值
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = ArrayList.this.modCount;
            } catch (final IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();
            }
        }
    }

28)清空 ArrayList

    /**
     * 清空数组元素和 size
     */
    @Override
    public void clear() {
        modCount++;        final Object[] es = this.elementData;        // 将对象数组前 size 个元素置为 null
        for (int to = this.size, i = this.size = 0; i < to; i++) {
            es[i] = null;
        }
    }

原文出处:https://www.cnblogs.com/zhuxudong/p/9581072.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消