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);
- }
- @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;
- }
- ...... //看的出来,这个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 <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
- @Override
- public void forEach(Consumer<? super E> action) {
- action.accept(element);
- }
- @Override
- public boolean removeIf(Predicate<? super E> filter) {
- throw new UnsupportedOperationException();
- }
- @Override
- public void replaceAll(UnaryOperator<E> operator) {
- throw new UnsupportedOperationException();
- }
- @Override
- public void sort(Comparator<? super E> c) {
- }
- @Override
- 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
Java踩坑之List的removeAll方法的更多相关文章
- java踩坑记
1.String 相等 稍微有点经验的程序员都会用equals比较而不是用 ==,但用equals就真的安全了吗,看下面的代码 user.getName().equals("xiaoming ...
- 『OGG 02』Win7 配置 Oracle GoldenGate Adapter Java 踩坑指南
上一文章 <__Win7 配置OGG(Oracle GoldenGate).docx>定下了 两个目标: 目标1: 给安装的Oracle_11g 创建 两个用户 admin 和 root ...
- Java踩坑之路
陆陆续续学Java也快一年多了,从开始的一窍不通到现在的初窥门径,我努力过,迷茫过,痛过,乐过,反思过,沉淀过.趁着新年,我希望能把这些东西记下来,就当是我一路走来的脚印. 一.初识网站应用 记得第一 ...
- JAVA踩坑录
以前踩了很多坑,大多忘了.现在踩了坑,想起了一定记下来. 1. 字符串分割,这种工具类,首次使用一定要先看一眼,不然跳坑 commons-lang StringUtils.split分割时会去掉空串: ...
- java踩坑
1. java判断两个字符串是否相等用equals 2. java只传递指针遇到的坑: 1 import java.util.*; 2 3 public class mapTest { 4 publi ...
- Java踩坑记系列之Arrays.AsList
java.util.Arrays的asList方法可以方便的将数组转化为集合,我们平时开发在初始化ArrayList时使用的比较多,可以简化代码,但这个静态方法asList()有几个坑需要注意: 一. ...
- mongo java 踩坑记
为什么会有这么多坑 1. Java会把 id:String = "合法ObjectId" 好心好意的 转为 _id:ObjectId 类型. 2. 为了避免第1点, 我定义了 ...
- Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- Android踩坑随笔Fragment中onActivityResult方法不被调用
最近项目里要做头像功能,参考了这篇博客(GitHub - zhudfly/SelectAvatarApplication: 一个选择并显示头像圆形控件,可以通过拍照或者选择相册中的图片来设置图片),但 ...
随机推荐
- 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 百篇博客分析OpenHarmony源码 | v25.01
百篇博客系列篇.本篇为: v25.xx 鸿蒙内核源码分析(并发并行篇) | 听过无数遍的两个概念 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...
- 【Go】Golang实现gRPC的Proxy的原理
背景 gRPC是Google开始的一个RPC服务框架, 是英文全名为Google Remote Procedure Call的简称. 广泛的应用在有RPC场景的业务系统中,一些架构中将gRPC请求都经 ...
- vue-混入( mixin 更方便的组件功能复用方法)的使用
前言 vue 中组件完成了样式和功能的综合复用,通过自定义指令完成了一部分功能的复用,本文总结一下混入在vue项目开发中提供的非常便利的功能复用. 正文 1.混入的分类 (1)全局混入 <div ...
- VUE自学日志01-MVC和MVVM
一.需要了解的基础概念 Model(M)是指数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开.这里的难点主要在于需要和前端约定统一的接口规则. View(V)是视图层,也就是 ...
- Serverless 架构到底要不要服务器?
作者 | aoho 来源 | Serverless 公众号 Serverless 是什么? Serverless 架构是不是就不要服务器了?回答这个问题,我们需要了解下 Serverless 是什么. ...
- Redis缓存穿透、缓存击穿、缓存雪崩的介绍及其解决方案
首先,来画一张图了解下缓存处理的流程 一.缓存穿透 描述: 缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求查询该数据,导致数据库压力过大. 解决方案: 1.接口校验 如鉴权校验.数据合法性 ...
- 云原生的弹性 AI 训练系列之三:借助弹性伸缩的 Jupyter Notebook,大幅提高 GPU 利用率
Jupyter Notebooks 在 Kubernetes 上部署往往需要绑定一张 GPU,而大多数时候 GPU 并没有被使用,因此利用率低下.为了解决这一问题,我们开源了 elastic-jupy ...
- 一个简单的单例模式Demo
/** * @author :nx014924 * @date :Created in 5/30/2021 1:09 PM * @description: * @modified By: * @ver ...
- Java:并发笔记-04
Java:并发笔记-04 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 本章内容-3 线程状态转换 活跃性 Lock 3.10 重新理解线程状态转换 假设有线 ...
- Mac 系统如何利用软链接在根目录创建文件夹?
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统 ...