Java踩坑之List的removeAll方法

    最近在公司写东西,发现List的removeAll方法报错 Demo代码如下:

                List ids1 = Arrays.asList(1L, 3L, 2L);
        List ids2 = Collections.singletonList(2L);
List ids3 = new ArrayList<>();
ids3.add(1L);
ids3.add(2L);
List ids = new ArrayList<>();
ids.add(2L);
System.out.println("==== 001");
ids1.removeAll(ids); // 这一步会报错
System.out.println("==== 002");
ids2.removeAll(ids); // 这一步也会报错
System.out.println("==== 003");
ids3.removeAll(ids);

    001报错的原因是:Arrays.asList 返回的List是自己内部实现的ArrayList 而不是util下的ArrayList对象

            /**
* Returns a fixed-size list backed by the specified array. (Changes to //明确指出 返回的是固定大小的list
* the returned list "write through" to the array.) This method acts
* as bridge between array-based and collection-based APIs, in
* combination with {@link Collection#toArray}. The returned list is
* serializable and implements {@link RandomAccess}.
*
*

This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
*


* List stooges = Arrays.asList("Larry", "Moe", "Curly");
*

*
* @param the class of the objects in the array
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static List asList(T... a) {
return new ArrayList<>(a);
}
            private static class ArrayList extends AbstractList
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[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class) 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;
}
...... //看的出来,这个list是可以修改的 但是要通过set方法
}

    所以调用removeAll方法的时候 会调用AbstractList的父类AbstractCollection的removeAll方法:

            public boolean removeAll(Collection c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}

    ArrayList是数组 在循环的时候删除元素 一定会出现问题


    002报错的原因是与001类似:Collections.singletonList的返回值SingletonSet也是自己的内部类

        
          

/**
* Returns an immutable list containing only the specified object. // 返回不可变的list
* The returned list is serializable.
*
* @param the class of the objects in the list
* @param o the sole object to be stored in the returned list.
* @return an immutable list containing only the specified object.
* @since 1.3
*/
public static List singletonList(T o) {
return new SingletonList<>(o);
}

        
          

private static class SingletonList
extends AbstractList
implements RandomAccess, Serializable {

private static final long serialVersionUID = 3093736618740652951L;

private final E element;

SingletonList(E obj) {element = obj;}

public Iterator iterator() {
return singletonIterator(element);
}

public int size() {return 1;}

public boolean contains(Object obj) {return eq(obj, element);}

public E get(int index) {
if (index != 0)
throw new IndexOutOfBoundsException("Index: "+index+", Size: 1");
return element;
}

// Override default methods for Collection
@Override
public void forEach(Consumer action) {
action.accept(element);
}
@Override
public boolean removeIf(Predicate filter) {
throw new UnsupportedOperationException();
}
@Override
public void replaceAll(UnaryOperator operator) {
throw new UnsupportedOperationException();
}
@Override
public void sort(Comparator c) {
}
@Override
public Spliterator spliterator() {
return singletonSpliterator(element);
}
}

    // 可以看出 这个list是一个只读的list 并未对外提供编辑方法

    同样会调用AbstractCollection的removeAll方法

    

    003是我new的ArrayList对象,会调用自己内部重写的removeAll方法,不会出问题,解决001、002的问题 最简单的办法可以用new ArrayList()包一层就ok了!


    究其原因还是自己对源码的研究不足!





你可能感兴趣的:(Java踩坑之List的removeAll方法)