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

  1. List<Long> ids1 = Arrays.asList(1L, 3L, 2L);
  2. List<Long> ids2 = Collections.singletonList(2L);
  3. List<Long> ids3 = new ArrayList<>();
  4. ids3.add(1L);
  5. ids3.add(2L);
  6. List<Long> ids = new ArrayList<>();
  7. ids.add(2L);
  8. System.out.println("==== 001");
  9. ids1.removeAll(ids); // 这一步会报错
  10. System.out.println("==== 002");
  11. ids2.removeAll(ids); // 这一步也会报错
  12. System.out.println("==== 003");
  13. ids3.removeAll(ids);

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

  1. /**
  2. * Returns a fixed-size list backed by the specified array. (Changes to //明确指出 返回的是固定大小的list
  3. * the returned list "write through" to the array.) This method acts
  4. * as bridge between array-based and collection-based APIs, in
  5. * combination with {@link Collection#toArray}. The returned list is
  6. * serializable and implements {@link RandomAccess}.
  7. *
  8. * <p>This method also provides a convenient way to create a fixed-size
  9. * list initialized to contain several elements:
  10. * <pre>
  11. * List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
  12. * </pre>
  13. *
  14. * @param <T> the class of the objects in the array
  15. * @param a the array by which the list will be backed
  16. * @return a list view of the specified array
  17. */
  18. @SafeVarargs
  19. @SuppressWarnings("varargs")
  20. public static <T> List<T> asList(T... a) {
  21. return new ArrayList<>(a);
  22. }
  1. private static class ArrayList<E> extends AbstractList<E>
  2. implements RandomAccess, java.io.Serializable
  3. {
  4. private static final long serialVersionUID = -2764017481108945198L;
  5. private final E[] a;
  6.  
  7. ArrayList(E[] array) {
  8. a = Objects.requireNonNull(array);
  9. }
  10.  
  11. @Override
  12. public int size() {
  13. return a.length;
  14. }
  15.  
  16. @Override
  17. public Object[] toArray() {
  18. return a.clone();
  19. }
  20.  
  21. @Override
  22. @SuppressWarnings("unchecked")
  23. public <T> T[] toArray(T[] a) {
  24. int size = size();
  25. if (a.length < size)
  26. return Arrays.copyOf(this.a, size,
  27. (Class<? extends T[]>) a.getClass());
  28. System.arraycopy(this.a, 0, a, 0, size);
  29. if (a.length > size)
  30. a[size] = null;
  31. return a;
  32. }
  33.  
  34. @Override
  35. public E get(int index) {
  36. return a[index];
  37. }
  38.  
  39. @Override
  40. public E set(int index, E element) {
  41. E oldValue = a[index];
  42. a[index] = element;
  43. return oldValue;
  44. }
  45.  
  46. @Override
  47. public int indexOf(Object o) {
  48. E[] a = this.a;
  49. if (o == null) {
  50. for (int i = 0; i < a.length; i++)
  51. if (a[i] == null)
  52. return i;
  53. } else {
  54. for (int i = 0; i < a.length; i++)
  55. if (o.equals(a[i]))
  56. return i;
  57. }
  58. return -1;
  59. }
  60. ...... //看的出来,这个list是可以修改的 但是要通过set方法
  61. }

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

  1. public boolean removeAll(Collection<?> c) {
  2. Objects.requireNonNull(c);
  3. boolean modified = false;
  4. Iterator<?> it = iterator();
  5. while (it.hasNext()) {
  6. if (c.contains(it.next())) {
  7. it.remove();
  8. modified = true;
  9. }
  10. }
  11. return modified;
  12. }

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

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

  1. /**
  2. * Returns an immutable list containing only the specified object. // 返回不可变的list
  3. * The returned list is serializable.
  4. *
  5. * @param <T> the class of the objects in the list
  6. * @param o the sole object to be stored in the returned list.
  7. * @return an immutable list containing only the specified object.
  8. * @since 1.3
  9. */
  10. public static <T> List<T> singletonList(T o) {
  11. return new SingletonList<>(o);
  12. }
  1. private static class SingletonList<E>
  2. extends AbstractList<E>
  3. implements RandomAccess, Serializable {
  4.  
  5. private static final long serialVersionUID = 3093736618740652951L;
  6.  
  7. private final E element;
  8.  
  9. SingletonList(E obj) {element = obj;}
  10.  
  11. public Iterator<E> iterator() {
  12. return singletonIterator(element);
  13. }
  14.  
  15. public int size() {return 1;}
  16.  
  17. public boolean contains(Object obj) {return eq(obj, element);}
  18.  
  19. public E get(int index) {
  20. if (index != 0)
  21. throw new IndexOutOfBoundsException("Index: "+index+", Size: 1");
  22. return element;
  23. }
  24.  
  25. // Override default methods for Collection
  26. @Override
  27. public void forEach(Consumer<? super E> action) {
  28. action.accept(element);
  29. }
  30. @Override
  31. public boolean removeIf(Predicate<? super E> filter) {
  32. throw new UnsupportedOperationException();
  33. }
  34. @Override
  35. public void replaceAll(UnaryOperator<E> operator) {
  36. throw new UnsupportedOperationException();
  37. }
  38. @Override
  39. public void sort(Comparator<? super E> c) {
  40. }
  41. @Override
  42. public Spliterator<E> spliterator() {
  43. return singletonSpliterator(element);
  44. }
  45. }
  46. // 可以看出 这个list是一个只读的list 并未对外提供编辑方法

同样会调用AbstractCollection的removeAll方法

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

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

更多技术资源请访问:https://www.zhaochao.top/articles

Java踩坑之List的removeAll方法的更多相关文章

  1. java踩坑记

    1.String 相等 稍微有点经验的程序员都会用equals比较而不是用 ==,但用equals就真的安全了吗,看下面的代码 user.getName().equals("xiaoming ...

  2. 『OGG 02』Win7 配置 Oracle GoldenGate Adapter Java 踩坑指南

    上一文章 <__Win7 配置OGG(Oracle GoldenGate).docx>定下了 两个目标: 目标1: 给安装的Oracle_11g 创建 两个用户 admin 和 root ...

  3. Java踩坑之路

    陆陆续续学Java也快一年多了,从开始的一窍不通到现在的初窥门径,我努力过,迷茫过,痛过,乐过,反思过,沉淀过.趁着新年,我希望能把这些东西记下来,就当是我一路走来的脚印. 一.初识网站应用 记得第一 ...

  4. JAVA踩坑录

    以前踩了很多坑,大多忘了.现在踩了坑,想起了一定记下来. 1. 字符串分割,这种工具类,首次使用一定要先看一眼,不然跳坑 commons-lang StringUtils.split分割时会去掉空串: ...

  5. java踩坑

    1. java判断两个字符串是否相等用equals 2. java只传递指针遇到的坑: 1 import java.util.*; 2 3 public class mapTest { 4 publi ...

  6. Java踩坑记系列之Arrays.AsList

    java.util.Arrays的asList方法可以方便的将数组转化为集合,我们平时开发在初始化ArrayList时使用的比较多,可以简化代码,但这个静态方法asList()有几个坑需要注意: 一. ...

  7. mongo java 踩坑记

    为什么会有这么多坑 1.  Java会把 id:String = "合法ObjectId"  好心好意的 转为  _id:ObjectId 类型. 2. 为了避免第1点, 我定义了 ...

  8. Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)

    在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...

  9. Android踩坑随笔Fragment中onActivityResult方法不被调用

    最近项目里要做头像功能,参考了这篇博客(GitHub - zhudfly/SelectAvatarApplication: 一个选择并显示头像圆形控件,可以通过拍照或者选择相册中的图片来设置图片),但 ...

随机推荐

  1. 深入浅出WPF-11.Template(模板)01

    模板 在WPF中,模板可以分为两大类: 控件模板(ControlTemplate)是算法内容的表现形式,一个控件怎么组织其内部的结构才能让它更符合业务逻辑,让用户操作更舒服,都是由她控制的.它决定了控 ...

  2. Unity——对象池管理

    Unity对象池管理 一.Demo展示 二.逻辑 在游戏中会出现大量重复的物体需要频繁的创建和销毁:比如子弹,敌人,成就列表的格子等: 频繁的创建删除物体会造成很大的开销,像这种大量创建重复且非持续性 ...

  3. 极简SpringBoot指南-Chapter03-基于SpringBoot的Web服务

    仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...

  4. Python中生成器的理解

    1.生成器的定义 在Python中一边循环一边计算的机制,称为生成器 2.为什么要有生成器 列表所有的数据都存在内存中,如果有海量的数据将非常耗内存 如:仅仅需要访问前面几个元素,那后面绝大多数元素占 ...

  5. FastAPI 学习之路(三十七)元数据和文档 URL

    你可以在 FastAPI 应用中自定义几个元数据配置. 你可以设定: Title:在 OpenAPI 和自动 API 文档用户界面中作为 API 的标题/名称使用. Description:在 Ope ...

  6. HCNP Routing&Switching之BGP路由宣告

    前文我们了解了BGP报文结构.类型以及邻居状态相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15422924.html:今天我们来聊一聊BGP路由宣告 ...

  7. Gopher们写if err != nil是否腻了?

    效果 go里面没有try catch,比较类似的有panic() 和 recover()机制,但是代价太大了,他们的场景更多使用在"程序异常,无法继续往下执行了这种场景",比如配置 ...

  8. seata整合nacos完成分布式的部署

    seata整合nacos完成分布式的部署 一.背景 二.部署机器 三.部署步骤 1.在seata上创建命名空间 2.下载对应版本的seata 3.单机启动 1.修改seata配置文件 1.修改注册中心 ...

  9. hystrix的dashboard和turbine监控

    当我们的应用程序使用了hystrix后,每个具体的hystrixCommand命令执行后都会产生一堆的监控数据,比如:成功数,失败数,超时数以及与之关联的线程池信息等.既然有了这些监控数据数据,那么我 ...

  10. spring social理解

    现在互联网飞速发展,人们每天在互联网上冲浪,获取各种信息.各大网站为了方便用户的登录,提供了各式各样的社交登录,比如:QQ.微信和微博登录等.这些主流的社交登录大多是基于oauth协议进行实现,spr ...