一:循环遍历list集合的四种方式

  • 简单for循环

  • iterator循环

  • 增加for循环

  • Lanbda表达式

二:四种遍历方式的用法示例

//简单for循环 
List<SalaryAdjustmentFile> fileList = new ArrayList<>();
fileList.add(new SalaryAdjustmentFile());
//此处省略加入list元素
for(int i = 0; n < fileList.size(); i++){
  .....//此处省略具体实现方法
}

//iterator循环
Iterator<SalaryAdjustmentFile> iter = fileList.iterator();
while(iter.hasNext()){
.....//此处省略具体实现方法
}

// 增强for循环
for(SalaryAdjustmentFile salaryAdjustmentFile : fileList){
.....//此处省略具体实现方法
}

//Lanbda表达式
fileList.stream().forEach(salaryAdjustmentFile -> {
.....//此处省略具体实现方法
});

三:删除集合元素

因为自己代码中是使用Lanbda表达式实现的list集合遍历,所以此处只展示这种方式遍历集合删除元素的功能
fileList.stream().forEach(salaryAdjustmentFile -> {
String staffId = salaryAdjustmentFile.getStaffId();
String modelFieldName = salaryAdjustmentFile.getModelFieldName();
String tenantId = BaseContextHandler.getTenantId();
String salaryPlanId = salaryAdjustmentFile.getSalaryPlanId();
SalaryAdjustmentFile last = salaryAdjustmentFileMapper.selectLastTimeFile(staffId,modelFieldName,salaryPlanId,tenantId);
Map map = salaryFileMapper.selectItemValueByStaffId(staffId,modelFieldName,salaryPlanId,tenantId);
if(StringUtils.isEmpty(last) && !map.isEmpty()){
salaryAdjustmentFile.setValueBeforeAdjustment((BigDecimal) map.get("itemValue"));
}else {
salaryAdjustmentFile.setValueBeforeAdjustment(last.getValueAfterAdjustment());
}
salaryAdjustmentFile.creat(idWorker.nextStringId());
//如果满足下面条件则删除元素
if((salaryAdjustmentFile.getValueBeforeAdjustment().subtract(salaryAdjustmentFile.getValueAfterAdjustment()) == BigDecimal.ZERO)){
fileList.remove(salaryAdjustmentFile);
}
});

上面的代码在运行的时候,并不会如我们期望的一样删除list元素成功,而是控制台会报错java.lang.NullPointerException: null

报错原因分析:
经过百度搜索了解到,这是并发修改异常错误,是集合遍历原理导致的,具体原因是这样的:

不管是哪种方式的集合遍历方法,当我们在遍历某个集合的时候,Collection的实现并没有同步化,如果在多线程应用程序中出现同时访问,而且出现修改操作的时候都要求外部操作同步化;调用遍历操作获得的遍历对象在多线程修改集合的时候也自动失效,并抛出java.util.ConcurrentModificationException。这种实现机制是fail-fast,对外部 的修改并不能提供任何保证。遍历对象在被创建的时候,同时创建了一张单链的索引表,指针指向原始数据对象,只能顺序读取,不能逆向操作,而set、list等集合是动态、可变的数据结构;当原始对象改变时,索引并为改变,因此,索引指针继续移动的时候,找不到要迭代的对象就会报错。

四:针对第三步中错误的解决方案

将删除对象放在一个临时的集合中,最后执行removeAll方法移除,如下:

List<SalaryAdjustmentFile> removeList = new ArrayList<>();
fileList.stream().forEach(salaryAdjustmentFile -> {
String staffId = salaryAdjustmentFile.getStaffId();
String modelFieldName = salaryAdjustmentFile.getModelFieldName();
String tenantId = BaseContextHandler.getTenantId();
String salaryPlanId = salaryAdjustmentFile.getSalaryPlanId();
SalaryAdjustmentFile last = salaryAdjustmentFileMapper.selectLastTimeFile(staffId,modelFieldName,salaryPlanId,tenantId);
Map map = salaryFileMapper.selectItemValueByStaffId(staffId,modelFieldName,salaryPlanId,tenantId);
if(StringUtils.isEmpty(last) && !map.isEmpty()){
salaryAdjustmentFile.setValueBeforeAdjustment((BigDecimal) map.get("itemValue"));
}else {
salaryAdjustmentFile.setValueBeforeAdjustment(last.getValueAfterAdjustment());
}
salaryAdjustmentFile.creat(idWorker.nextStringId());
//如果满足下面条件则删除元素
if((salaryAdjustmentFile.getValueBeforeAdjustment().subtract(salaryAdjustmentFile.getValueAfterAdjustment()) == BigDecimal.ZERO)){
removeList.add(salaryAdjustmentFile);
}
});
//删除掉集合中满足删除条件的数据
fileList.removeAll(removeList);

Lambda 表达式遍历集合时用remove方法删除list集合中满足条件的元素问题的更多相关文章

  1. java 数据类型:集合接口Collection之常用ArrayList;lambda表达式遍历;iterator遍历;forEachRemaining遍历;增强for遍历;removeIf批量操作集合元素(Predicate);

    java.util.Collection接口 Java的集合主要由两个接口派生出来,一个是Collection一个是Map,本章只记录Collection常用集合 集合只能存储引用类型数据,不能存储基 ...

  2. Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.HashMap; import java.util.Iterator; import ...

  3. Java List集合 遍历 四种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.ArrayList; import java.util.List; /** * @A ...

  4. Java Array数组 遍历 四种方式(包含 Lambda 表达式遍历)

    示例代码如下: package com.miracle.luna.lambda; import java.util.Arrays; /** * @Author Miracle Luna * @Date ...

  5. C#中分别对委托、匿名方法、Lambda表达式、Lambda表达式树以及反射执行同一方法的过程进行比较。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. 【转载】C#中List集合使用LastOrDefault方法查找出最后一个符合条件的元素

    在C#的List集合中,FirstOrDefault方法一般用来查找List集合中第一个符合条件的对象,如果未查到则返回相应默认值.其实如果要查找最后一个符合条件的List集合元素对象,可以使用Las ...

  7. 【转载】C#通过Remove方法移除DataTable中的某一列数据

    在C#中的Datatable数据变量的操作过程中,有时候我们需要移除当前DataTable变量中的某一列的数据,此时我们就需要使用到DataTable变量内部的Columns属性变量的Remove方法 ...

  8. 在Python的列表中利用remove()方法删除元素的教程

    在Python的列表中利用remove()方法删除元素的教程 这篇文章主要介绍了在Python的列表中利用remove()方法删除元素的教程,是Python入门中的基础知识,注意其和pop()方法的区 ...

  9. Lambda表达式遍历集合

    1.Collection Java 8 为Iterable接口新增了一个forEach(Consumer action)默认方法,该方法所需参数的类型是一个函数式接口,而Iterable接口是Coll ...

随机推荐

  1. 搞清楚C语言指针

    Part 0:为什么要写这篇文章 C语言中的指针是C语言的精髓,也是C语言的重难点之一. 然而,很少有教程能把指针讲的初学者能听懂,还不会引起歧义. 本文章会尝试做到这一点,如有错误,请指出. Par ...

  2. thinkphp5升级thinkphp6完整步骤

    在php.ini文件中  打开  php_openssl扩展,去掉前面的;extension=php_openssl.dll 在phpstudy的WWW目录打开cmd,输入composer creat ...

  3. 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...

  4. pytorch入门2.1构建回归模型初体验(模型构建)

    pytorch入门2.x构建回归模型系列: pytorch入门2.0构建回归模型初体验(数据生成) pytorch入门2.1构建回归模型初体验(模型构建) pytorch入门2.2构建回归模型初体验( ...

  5. ORM框架 Mybatis、Hibernate、Spring Data JPA之到底该用谁,谁更牛*

    在持久层框架中无可厚非的就是mybatis了,但是也会经常被人问到为啥要用mybatis,为啥不用hibernate,jpa.很多人各级都是地铁爷爷看手机的表情,似乎从来没想过这个问题.“公司叫用我就 ...

  6. 多线程高并发编程(10) -- ConcurrentHashMap源码分析

    一.背景 前文讲了HashMap的源码分析,从中可以看到下面的问题: HashMap的put/remove方法不是线程安全的,如果在多线程并发环境下,使用synchronized进行加锁,会导致效率低 ...

  7. OO第三单元——JML之破分大法

    一.Jml总结及应用工具链 总的来说,jml就是对java程序进行规格化设计的一种表示语言,其中最核心的就是规格化,将代码要实现的功能和各项要求与约束不是通过自然语言,而是通过严密的逻辑语言来表达,这 ...

  8. Redis 数据结构 之 SDS

    SDS(simple dynamic string),简单动态字符串.s同时它被称为 Hacking String.hack 的地方就在 sds 保存了字符串的长度以及剩余空间.sds 的实现在 sd ...

  9. MySQL的使用方法和视图、索引、以及存储过程的一些简单方法

    一,基本概念 1, 常用的两种引擎:         (1) InnoDB        a,支持ACID,简单地说就是支持事务完整性.一致性:         b,支持行锁,以及类似ORACLE的一 ...

  10. java并发——copyonwrite

    今天在网上看到一个问题,问除了加锁之外,有没有其他方法来保证线程安全? ---- copyonwrite机制 一.copyonwrite机制 机制实现:写时复制, 在往集合中添加数据的时候,先拷贝存储 ...