资讯专栏INFORMATION COLUMN

说一说java.util.Arrays$ArrayList

linkin / 1422人阅读

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

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

使用场景对比

构造拥有三个字符串的List
ArrayList

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

Arrays$ArrayList

List la = Arrays.asList("a", "b", "c");
//源码
public static  List 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 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 iterator() {
        return new Itr();
    }
    private class Itr implements Iterator {
        //...省略
        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 la = Arrays.asList("a", "b", "c");
la.remove("e");

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68920.html

相关文章

  • 数组和列表的转换问题

    摘要:以下指代数组,指代数组列表。常见的转换方法是或。在的使用过程中需要注意,当要转换的长度小于的时,不要试图通过传入形参的方式进行转换,虽然这在的长度大于时不会出现问题。所以,极度建议在转换之前初始化的长度为的,并且使用返回值重新给赋值。 Array 和 List 都是我们在开发过程中常见的数据结构。我们都知道 Array 是定长的,List 是可变长。而且,List 的实现类 Array...

    ChristmasBoy 评论0 收藏0
  • Java程序员常犯的10个错误

    摘要:原文出自本文总结了程序员常犯的个错误。可以看看为什么在中被设计成不可变父类和子类的构造函数以上这段代码出现编译错误,因为默认的父类构造函数未定义。如果程序员定义构造函数,编译器将不插入默认的无参数构造函数。 原文出自:http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/ 本文总结了J...

    Andrman 评论0 收藏0
  • Java编程基础17——集合(List集合)

    1_(去除ArrayList中重复字符串元素方式)* A:案例演示 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同) 思路:创建新集合方式 import java.util.ArrayList; import java.util.Iterator; public class ArrayList_1_demo { /* 创建新集合将重复元素去掉 * 1.明...

    scola666 评论0 收藏0
  • JAVA学习之路 (十)集合

    摘要:集合中的集合是一种工具类,就像是容器,存储任意数量的具有共同属性的对象集合的作用在类的内部,对数据进行组织简单而快速的搜索大量数目的条目有的集合接口,提供了一系列排列有序的元素,并且可以在序列中进行快速的插入和删除有些集合接口,提供了映射关 集合 java中的集合: 是一种工具类,就像是容器,存储任意数量的具有共同属性的对象 集合的作用 1. 在类的内部,对数据进行组织 2. 简单而快...

    sutaking 评论0 收藏0
  • Stream流与Lambda表达式(一) 杂谈

    摘要:一流转换为数组集合陈杨将流转换为数组将流转换为数组将流转换为集合将流转换为集合解析 一、流 转换为数组、集合 package com.java.design.java8.Stream; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context...

    Harpsichord1207 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<