zoukankan      html  css  js  c++  java
  • Java容器探索-为何Arrays.asList()方法产生的List调用Iterator.remove()报错,new ArrayList()产生的ArrayList就能正常移除

    1. new ArrayList产生的ArrayList是java.util.ArrayList

    1. ArrayList继承了抽象类AbstractList:
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    
    1. ArrayList有个内部类实现了Iterator,该内部类实现了remove()方法
    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();
            }
        }
    }
    
    1. ArrayList重新了AbstractList的public E remove(int index)方法,说白了就是数组的重新copy过程
    public E remove(int index) {
        rangeCheck(index);
    
        modCount++;
        E oldValue = elementData(index);
    
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    
        return oldValue;
    }
    

    2. Arrays.asList()产生的ArrayList是Arrays的一个内部类

    1. Arrays.asList()通过new自己内部类ArrayList返回一个List
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
    
    1. Arrays内部类ArrayList继承了AbstractList
    private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{
    private static final long serialVersionUID = -2764017481108945198L;
    private final E[] a;
    
    ArrayList(E[] array) {
        a = Objects.requireNonNull(array);
    }
    
    @Override
    public int size() {
        return a.length;
    }
    
    @Override
    public Object[] toArray() {
        return a.clone();
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        int size = size();
        if (a.length < size)
            return Arrays.copyOf(this.a, size,
                                 (Class<? extends T[]>) a.getClass());
        System.arraycopy(this.a, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }
    
    @Override
    public E get(int index) {
        return a[index];
    }
    
    @Override
    public E set(int index, E element) {
        E oldValue = a[index];
        a[index] = element;
        return oldValue;
    }
    
    @Override
    public int indexOf(Object o) {
        E[] a = this.a;
        if (o == null) {
            for (int i = 0; i < a.length; i++)
                if (a[i] == null)
                    return i;
        } else {
            for (int i = 0; i < a.length; i++)
                if (o.equals(a[i]))
                    return i;
        }
        return -1;
    }
    
    1. 可以发现该内部类没有重写AbstractList的public E remove(int index)方法。所以调用该方法,其实就是调用AbstractList的该方法,看看该方法源码。
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }
    

    到此已经彻底明白为什么Arrays.asList()方法产生的List调用Iterator.remove()会报错了

    3. 总结

    归根到底,这两种方式产生的ArrayList就不是一个类,一个是Arrays的内部类,该类remove方法直接调用AbstractList的实现;另一个是java.util.ArrayList该类重写了remove和remove(int index)方法。

    只有把命运掌握在自己手中,从今天起开始努力,即使暂时看不到希望,也要相信自己。因为比你牛几倍的人,依然在努力。
  • 相关阅读:
    IDEA导入项目后,导入artifacts 方法 以及 Spring的配置文件找不到的解决方法
    Tomcat8中如何内存溢出,如何增大内存?
    SpringSecurity-权限关联与控制
    学习黑马教学视频SSM整合中Security遇到的问题org.springframework.security.access.AccessDeniedException: Access is denied
    SSM项目中,关于Test类中不能使用Autowired注入bean的问题
    spring mvc绑定参数之 类型转换 有三种方式:
    maven缺失ojdbc6解决方案 :Missing artifact com.oracle:ojdbc6:jar:11.2.0.1.0问题解决 ojdbc包pom.xml出错
    学习SpringMVC 文件上传 遇到的问题,403:returned a response status of 403 Forbidden ,409文件夹未找到
    【转】Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍
    Protocol buffers--python 实践 简介以及安装与使用
  • 原文地址:https://www.cnblogs.com/freesky168/p/14358179.html
Copyright © 2011-2022 走看看