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)方法。

    只有把命运掌握在自己手中,从今天起开始努力,即使暂时看不到希望,也要相信自己。因为比你牛几倍的人,依然在努力。
  • 相关阅读:
    滑动加载
    关于git的常用命令
    github相关指令学习
    jquery的contains方法
    vertical-align_CSS参考手册_web前端开发参考手册系列
    关于拜读张鑫旭文章,了解的新属性
    如何从GitHub仓库clone项目
    关于小窗滑动,父级body也跟随滑动的解决方案(2)
    vue父子组件传递参数之props
    JsExcelXml.js的源码
  • 原文地址:https://www.cnblogs.com/freesky168/p/14358179.html
Copyright © 2011-2022 走看看