说一说java.util.Arrays.ArrayList

java.util.Arrays.ArrayList(下文:Arrays.ArrayList)是java.util.Arrays的私有静态内部类,他实现的接口,继承的父类几乎和java.util.ArrayList(下文:ArrayList)相同,既然是私有的,那么平常应该是我们少关注的地方。本文尝试对比一两个他们之间的不同点。

使用场景对比

构造拥有三个字符串的ListArrayList

List<String> lb = new ArrayList<>(3);
        lb.add("a");
        lb.add("b");
        lb.add("c");

Arrays.ArrayList

List<String> la = Arrays.asList("a", "b", "c");
//源码
public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

两者都满足了需求,后者看起来比前者简洁,除此之外两者还有什么不同呢。

增加删除操作对比

支持的操作,

lb.add("d")
lb.remove("d")

不支持的操作,这将会抛出异常java.lang.UnsupportedOperationException

la.add("d")
la.remove("d")

可见Arrays.ArrayList不允许增加也不允许删除。

具体的add方法

Arrays.ArrayList类, 首先并没有override父类的add方法,所以这个方法来自他的父类AbstractList; 看AbstractList中的add方法

    public boolean add(E e) {
        add(size(), e);
        return true;
    }
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }    

最终调用的方法抛出了异常UnsupportedOperationException。 相比较ArrayList

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

这两个方法都在ArrayList中实现了,或者扩容然后在尾部插入,或者扩容、移动数组元素,然后插入到指定的下标位置。

具体的remove方法

Arrays.ArrayListremove(Object)方法继承自AbstractList的父类AbstractCollection,其中

    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }

这里使用了迭代器的方式进行删除,看这个方法的注释

如果这个迭代器没有实现remove方法的话,那么这整个方法也将要抛出UnsupportedOperationException异常的。 在AbstractCollectioniterator是一个抽象方法,之于Arrays.ArrayList,这个方法实现的位置还是在AbstractList

    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //...省略
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }    
    }

到这里我们发现AbstractList实现了AbstractCollectioniterator方法,而且返回的迭代器也实现了remove方法,不是上文提到的注释那种情况。但是为什么删除动作还是不允许的呢? 具体这个迭代器的remove方法,

AbstractList.this.remove(lastRet);

可见迭代器最终也是调用容器类的remove方法的,那么Arrays.ArrayList没有实现remove方法,而AbstractListremove方法,如下

    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

因此,即使在AbstractList中使用迭代器进行删除操作,但由于Arrays.ArrayList没有实现remove且继承的remove抛出UnsupportedOperationException异常,最终在Arrays.ArrayList是不允许删除操作的。

值得注意的是,AbstractList的迭代器是否要调用remove(int)方法是由要删除的目标是否数组的元素决定的,如果不存在这样的元素,则下面的代码并不会出现异常,

List<String> la = Arrays.asList("a", "b", "c");
la.remove("e");

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互扯程序

Java集合深度解析之ArrayList

KS Knowledge Sharing 知识分享 现在是资源共享的时代,同样也是知识分享的时代,如果你觉得本文能学到知识,请把知识与别人分享。 转自:...

22460
来自专栏Bingo的深度学习杂货店

Q108 Convert Sorted Array to Binary Search Tree

Given an array where elements are sorted in ascending order, convert it to a hei...

32530
来自专栏数据结构与算法

2879 堆的判断

2879 堆的判断 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 堆是一种常用...

32680
来自专栏芋道源码1024

Jedis 对 Redis 的操作详解

本篇主要阐述Jedis对redis的五大类型的操作:字符串、列表、散列、集合、有序集合。

23130
来自专栏IT可乐

JDK1.8源码(五)——java.util.ArrayList 类

  关于 JDK 的集合类的整体介绍可以看这张图,本篇博客我们不系统的介绍整个集合的构造,重点是介绍 ArrayList 类是如何实现的。 1、ArrayLis...

423110
来自专栏LeetCode

leetCode 77&39. Combinations & Combination Sum

Given two integers n and k, return all possible combinations of k numbers out of...

12500
来自专栏余林丰

Java迭代器Iterator

 之前我们实现了迭代器模式,很多编程语言实际上已经内置了迭代器类,比如Java就为我们实现了迭代器Iterator。我们首先来看Iterator中的源码。 通过...

267100
来自专栏java一日一条

Java 容器&泛型(1):认识容器

容器是Java语言学习中重要的一部分。泥瓦匠我的感觉是刚开始挺难学的,但等你熟悉它,接触多了,也就“顺理成章”地知道了。Java的容器类主要由两个接口派生而出:...

12520
来自专栏机器学习入门

LWC 52:687. Longest Univalue Path

LWC 52:687. Longest Univalue Path 传送门:687. Longest Univalue Path Problem: Given...

23970
来自专栏张俊红

数据结构—线性表

本篇开始,又会开始一个新的系列,数据结构,数据结构在算法或者是编程中的重要性不言而喻,所以学好数据结构还是很有必要的。本篇主要介绍数据结构的第一个结构——线性表...

14130

扫码关注云+社区

领取腾讯云代金券