Java踩坑之List的removeAll方法
最近在公司写东西,发现List的removeAll方法报错 Demo代码如下:
-
List<Long> ids1 = Arrays.asList(1L, 3L, 2L);
-
List<Long> ids2 = Collections.singletonList(2L);
-
List<Long> ids3 = new ArrayList<>();
-
ids3.add(1L);
-
ids3.add(2L);
-
List<Long> 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}.
-
*
-
* <p>This method also provides a convenient way to create a fixed-size
-
* list initialized to contain several elements:
-
* <pre>
-
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
-
* </pre>
-
*
-
* @param <T> 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 <T> List<T> asList(T... a) {
-
return new ArrayList<>(a);
-
}
-
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);
-
}
-
-
-
public int size() {
-
return a.length;
-
}
-
-
-
public Object[] toArray() {
-
return a.clone();
-
}
-
-
-
-
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;
-
}
-
-
-
public E get(int index) {
-
return a[index];
-
}
-
-
-
public E set(int index, E element) {
-
E oldValue = a[index];
-
a[index] = element;
-
return oldValue;
-
}
-
-
-
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
-
Objects.requireNonNull(c);
-
boolean modified = false;
-
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 <T> 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 <T> List<T> singletonList(T o) {
-
return new SingletonList<>(o);
-
}
-
private static class SingletonList<E>
-
extends AbstractList<E>
-
implements RandomAccess, Serializable {
-
-
private static final long serialVersionUID = 3093736618740652951L;
-
-
private final E element;
-
-
SingletonList(E obj) {element = obj;}
-
-
public Iterator<E> 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
-
-
public void forEach(Consumer<? super E> action) {
-
action.accept(element);
-
}
-
-
public boolean removeIf(Predicate<? super E> filter) {
-
throw new UnsupportedOperationException();
-
}
-
-
public void replaceAll(UnaryOperator<E> operator) {
-
throw new UnsupportedOperationException();
-
}
-
-
public void sort(Comparator<? super E> c) {
-
}
-
-
public Spliterator<E> spliterator() {
-
return singletonSpliterator(element);
-
}
-
}
-
// 可以看出 这个list是一个只读的list 并未对外提供编辑方法
同样会调用AbstractCollection的removeAll方法
003是我new的ArrayList对象,会调用自己内部重写的removeAll方法,针对数组重写了删除方法,不会出问题,解决001、002的问题 最简单的办法可以用new ArrayList()包一层就ok了!
究其原因还是自己对源码的研究不足!
更多技术资源请访问:https://www.zhaochao.top/articles