当前位置: 代码迷 >> 综合 >> Java容器探索-为何Arrays.asList()方法产生的List调用Iterator.remove()报错,new ArrayList()产生的ArrayList就能正常移除
  详细解决方案

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

热度:80   发布时间:2023-12-15 06:21:57.0

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

  相关解决方案