1.情景展示

已知json对象MainExt

需要把值为空数组的key移除掉,下面是执行代码

执行结果报错:java.util.ConcurrentModificationException

2.原因分析

大致过程就是:

符合删除条件--》调用remove()方法后,expectedModCount-1-1,而modCount-1,在进行下次遍历,也就是执行next()方法体里,又去调用了checkForComodification()方法,

检查modCount和expectedModCount两者的值不一致,所以会抛出ConcurrentModificationException异常。

3.错误示例

错误实现一

Iterator iterator = MainExt.keySet().iterator();

while(iterator.hasNext()) {

String key = iterator.next();

if ("[]".equals(MainExt.get(key).toString())) {

MainExt.remove(key);

}

}

起初,使用迭代器发现还是失败,因为在调用next()方法时,又去调用了remove()方法。

错误实现二

JSONObject MainExt2 = new JSONObject(MainExt);

MainExt2.forEach((k,v) -> {

if ("[]".equals(v.toString())) {

MainExt.remove(k);

}

});

我们咋一看,已经创建了一个新的对象,并将MainExt的值赋给了MainExt2,但是,通过迭代MainExt2,移除MainExt的子节点,移除失败,

这才让我意识到,MainExt2并没有和MainExt切断联系,换句话说就是:MainExt2对MainExt的引用,并不是真正意义上的深层拷贝,要想成功,数据完成拷贝后必须切断联系。

4.正确方式

String str = "{\n" +

" \"MedicalType\": \"门诊\",\n" +

" \"PatientNumber\": \"202009041167\",\n" +

" \"MedicalDate\": \"20200904-11:41:31\",\n" +

" \"OrgType\": \"综合医院\",\n" +

" \"MedicalInsuranceType\": [],\n" +

" \"MedicalInsuranceID\": [],\n" +

" \"Gender\": [],\n" +

" \"FundPayAmount\": \"0.00\",\n" +

" \"OtherPayAmount\": \"0.00\",\n" +

" \"AccountPayAmount\": \"0.00\",\n" +

" \"OwnPayAmount\": \"0.00\",\n" +

" \"SelfpaymentAmount\": \"0.00\",\n" +

" \"SelfpaymentCost\": \"0.00\"\n" +

" }";

JSONObject MainExt = JSONObject.parseObject(str);

// 深拷贝,不拷贝直接移除key的话,会报错:ConcurrentModificationException

JSONObject MainExt2 = (JSONObject) MainExt.clone();

MainExt2.forEach((k,v) -> {

if ("[]".equals(v.toString())) {

MainExt.remove(k);

}

});

通过深层拷贝,复制一份原数据,并与原来对象切断联系,迭代复制后的数据,移除原对象的数据。

说明:说到底,lambda表达式是无法实现对同一对象遍历的同时,并完成移除子元素的。

5.list集合移除节点

List list = new ArrayList<>();

list.add("Marydon");

list.add("18");

list.add("test");

这里需要注意的是:list集合的大小不能为2,如果是2的话,下面无论是哪一种方式都能正常移除!!!

错误方式一:for循环

for (int i = 0; i < list.size(); i++) {

if ("Marydon".equals(list.get(i))) {

list.remove(i);

}

}

System.out.println(list);

错误方式二:foreach

for (String s : list) {

if ("Marydon".equals(s)) {

list.remove(s);

}

}

错误方式三:通过list移除

Iterator ite = list.iterator();

while (ite.hasNext()) {

String next = ite.next();

if (next.equals("Marydon")) {

list.remove(next);

}

}

正确方式一:通过迭代器移除

Iterator ite = list.iterator();

while (ite.hasNext()) {

if (ite.next().equals("Marydon")) {

ite.remove();

}

}

20200907

方式二:removeAll()

// 存储将要移除的元素

List removeList = new ArrayList<>();

for (String s : list) {

if (s.equals("Marydon")) {

removeList.add(s);

}

}

// 移除

list.removeAll(removeList);

System.out.println(list);

20200908

方式三:ArrayList.clone()

// 复制list

List newList = (List) ((ArrayList) list).clone();

// 遍历复制的list

newList.forEach(e -> {

if ("Marydon".equals(e)) {

// 移除原来的list子元素

list.remove(e);

// 结束本轮循环(可有可无)

return;

}

});

System.out.println(list);

写在最后

哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

相关推荐:

lamuda表达式 list移除空元素_java8 Lambda表达式遍历并移除元素,报错:ConcurrentModificationException的解决办法...相关推荐

  1. Lambda01 编程范式、lambda表达式与匿名内部类、函数式接口、lambda表达式的写法...

    1 编程范式 主要的编程范式有三种:命令式编程,声明式编程和函数式编程. 1.1 命令式编程 关注计算机执行的步骤,就是告诉计算机先做什么后做什么 1.2 声明式编程 表达程序的执行逻辑,就是告诉计算 ...

  2. java8 Lambda表达式的应用(函数式接口、lambda表达式,方法引用及Stream API)

    之前写了一篇博客简单介绍了一下java 8发布新增的一些特性功能,java 8在2014年发布,距今也不少年了,但是lambda表达式使用并不熟练,现在一边学习,一边记录一下. 目录 一.Lambda ...

  3. Lambda表达式到底是什么?——简单了解Lambda表达式

    一.Lambda表达式是什么 简单来说,Lambda表达式是一个可传递的代码段.可以不借助对象传递的一个代码段.那java作为一个面向对象的语言,为什么要加入这么一个特性呢? 二.为什么使用Lambd ...

  4. java 拉姆表达式_Java8 lambda表达式10个示例

    Java 8 lambda表达式示例 转自importNew 原文链接 例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现R ...

  5. 精通lambda表达式:java多核编程_Java8 Lambda表达式和流操作如何让你的代码变慢5倍...

    有许许多多关于 Java 8 中流效率的讨论,但根据 Alex Zhitnitsky 的测试结果显示:坚持使用传统的 Java 编程风格--iterator 和 for-each 循环--比 Java ...

  6. lambda表达式方法泛型_模板方法模式–使用Lambda表达式,默认方法

    lambda表达式方法泛型 模板方法模式是Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides在著名的< 设计模式>一书中解释的23种 ...

  7. Unity2019新建空项目都报错(有两个看不到的红色报错)怎么解决?

    Unity2019新建空项目都报错(有两个看不到的红色报错) 如下图所示. 正经解决方案:完全卸载重装Unity和hub.或者升级Unity到2020或以上版本. 不正经解决方案:跳过Unity hu ...

  8. lambda表达式python菜鸟教程_[c#菜鸟]lambda表达式

    what 一.定义 Lambda 表达式是一种可用于创建 委托 或 表达式目录树 类型的 匿名函数 .通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数.(微软) 理 ...

  9. 运行差分灰狼时出现 关于“索引超出数组元素的数目(0)和矩阵维度问题以及图例的问题”的解决办法

    问题一:索引超出数组元素的数目(0) 看截图,上面注释掉的libsvmpredict是出错的, 下面一句是修改后的. [~,~,fitness]=libsvmpredict(output_test,i ...

最新文章

  1. 第九课.深度学习常见内容补充
  2. Enterprise search result view column显示technical name
  3. BugkuCTF-PWN题pwn7-repeater详细讲解多解法
  4. LeetCode 637. 二叉树的层平均值
  5. java怎么连不上xml_java mvc web 项目web.xml头改错了,死活加载不上springMvc的jar
  6. iphone 目录大全
  7. 移远ec20模式与切换
  8. springboot 架构图
  9. K8s(3):资源清单
  10. selenium 远程调用浏览器
  11. 如何给运行中的docker容器增加映射端口
  12. 全屏的微粒子3D动画特效
  13. ffmpeg中音频解码方法(附代码)+ffmpeg音频解码播放速度快的问题(随手笔记,以供查阅)
  14. python音乐播放器
  15. 【第二趴】uni-app开发工具(手把手带你安装HBuilderX、搭建第一个多端项目初体验)
  16. EC20使用之 quectel-CM的启动
  17. ShardingSphere 学习
  18. socket.io 工具
  19. 2022-2028年中国国际货运代理行业市场竞争态势及未来前景分析报告
  20. 迪文触摸串口屏 实例应用(1)——安装编译和下载

热门文章

  1. linux中Cron定时任务系统命令详解
  2. MFC中打开指定文件夹并默认选中该文件夹中的某个文件
  3. 删除苹果自带软件后果_ghost explorer工具怎么删除ghost自带软件【详细教程】
  4. 矩形法_教程 | 三个案例教会你大师都爱用的矩形造字法!
  5. UE4如何解析命令行参数
  6. SQL表连接,排序输出
  7. 利用xlwt、xlrd搜索excel表格内容并复制出需要的那一行内容
  8. 客户端和服务器实现全双工通信(基于线程)
  9. 问题1:UIView不会被释放--block中如果有self的话会造成循环引用
  10. Gartner:克服SIEM部署失败的通病