Java中循环删除List中元素

版权声明:未经博主本人同意,请勿私自转发分享。 https://blog.csdn.net/Nerver_77/article/details/84070222
Java中循环删除List中元素

写在开头:最近在处理一个包装类时候,把Mapper查询到的数据暂存到了ArrayList中,后续做循环遍历删除操作的时候,当时采用了foreach循环,结果弹出了ConcurrentModificationException错误。于是乎就在博客上找解决方案,最后整理总结一下。

遍历方式:
for、foreach、iterator

常规需求:
删除一个、多个元素

准备工作:User实体类、初始化UserList

// 初始化列表
List<User> list = User.getUserList();
// 遍历列表元素
showAll(list);

结果:

展示当前列表数据
User{name='name0', age=0, address='address0'}
User{name='name1', age=1, address='address1'}
User{name='name2', age=2, address='address2'}
User{name='name3', age=3, address='address3'}
User{name='name4', age=4, address='address4'}

for

  1. 删除单个元素:

     // for
     for (int i = 0; i< list.size(); i++) {
         if (list.get(i).getAge() == 2) {
             list.remove(list.get(i));
         }
     }
     showAll(list);
    

    结果:正常

     User{name='name0', age=0, address='address0'}
     User{name='name1', age=1, address='address1'}
     User{name='name3', age=3, address='address3'}
     User{name='name4', age=4, address='address4'}
    
  2. 删除多个元素:

     变更控制条件:list.get(i).getAge() > 2
    

    结果:age=3的元素被删除,为何age=4的元素未被删除呢?

     User{name='name0', age=0, address='address0'}
     User{name='name1', age=1, address='address1'}
     User{name='name2', age=2, address='address2'}
     User{name='name4', age=4, address='address4'}
    
  3. 总结:
    List列表在删除某个元素之后,list.size()发生了变化,除此之外,元素的索引index也在发生变化,所以当删除某个元素之后,根据元素索引继续进行遍历,这样就很有可能会漏掉某些元素。因此,list.remove()方式建议删除特定元素,不建议用于删除多个元素。

  4. 补充说明:特定元素,具有唯一性的元素,亦或者判定条件具有唯一性

    比如:我们将列表数据的age属性全部置为2,即:

     User{name='name0', age=2, address='address0'}
     User{name='name1', age=2, address='address1'}
     User{name='name2', age=2, address='address2'}
     User{name='name3', age=2, address='address3'}
     User{name='name4', age=2, address='address4'}
    

    我们再进行删除单个元素的操作会发现结果:

     User{name='name1', age=2, address='address1'}
     User{name='name3', age=2, address='address3'}
    

    验证了我们上述总结,我们简单叙述下遍历流程:当对元素删除之后,后续元素将整体向前移动覆盖(copy)

     第一次:user:i = 0 -> name0 -> 符合条件 -> remove -> size=4 , i++	
     User{name='name1', age=2, address='address1'}
     User{name='name2', age=2, address='address2'}
     User{name='name3', age=2, address='address3'}
     User{name='name4', age=2, address='address4'}
     
     第二次:user:i = 1 -> name2 -> 符合条件 -> remove -> size=3 , i++
     User{name='name1', age=2, address='address1'}
     User{name='name3', age=2, address='address3'}
     User{name='name4', age=2, address='address4'}
     
     第三次:user:i = 2 -> name4 -> 符合条件 -> remove -> size=2 , i++
     User{name='name1', age=2, address='address1'}
     User{name='name3', age=2, address='address3'}
     
     第四次:user:i = 3 -> i > list.size -> 跳出循环
    

foreach

  1. 删除单个元素**(删除多个元素同for)**

     // foreach
     for (User user : list) {
         if (user.getAge() == 2) {
             list.remove(user);
         }
     }
     showAll(list);
    

结果:java.util.ConcurrentModificationException 异常

	User{name='name0', age=0, address='address0'}
	User{name='name1', age=1, address='address1'}
	User{name='name2', age=2, address='address2'}
	User{name='name3', age=3, address='address3'}
	User{name='name4', age=4, address='address4'}

分析:

删除元素后继续循环会报错误信息ConcurrentModificationException,因为元素在使用的时候发生了并发的修改,抛出异常。

并发修改:list.remove() + 索引推进

解决方案:添加break,强制跳出循环遍历

// foreach
for (User user : list) {
    if (user.getAge() == 2) {
        list.remove(user);
        break;
    }
}
showAll(list);

结果:可以正常删除

User{name='name0', age=0, address='address0'}
User{name='name1', age=1, address='address1'}
User{name='name3', age=3, address='address3'}
User{name='name4', age=4, address='address4'}

iterator

迭代器遍历方式:建议使用

删除单个、多个元素:

// iterator
Iterator<User> iterator = list.iterator();
while (iterator.hasNext()) {
    if (iterator.next().getAge() > 2) {
        iterator.remove();
    }
}
showAll(list);

结果:

User{name='name0', age=0, address='address0'}
User{name='name1', age=1, address='address1'}
User{name='name2', age=2, address='address2'}

补充说明:

采用迭代器方式进行遍历,可以正常循环以及单个、多个元素删除,需要特别注意:remove方法要使用iterator,而不是list的remove方法

迭代器(Iterator)

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象。迭代器通常被称为“轻量级”对象。

Java中的Iterator功能比较简单,并且只能单向移动:

  1. 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。

     注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
    
  2. 使用next()获得序列中的下一个元素。

  3. 使用hasNext()检查序列中是否还有元素。

  4. 使用remove()将迭代器新返回的元素删除。

Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

猜你喜欢

转载自blog.csdn.net/Nerver_77/article/details/84070222