当前位置: 首页 > 编程笔记 >

java 如何实现正确的删除集合中的元素

陈博容
2023-03-14
本文向大家介绍java 如何实现正确的删除集合中的元素,包括了java 如何实现正确的删除集合中的元素的使用技巧和注意事项,需要的朋友参考一下

在java中如果我们需要遍历集合并删除其中的某些元素时,例如对于List来说,我们有三种办法。

1. 普通的for循环遍历并删除

public void forRemove(List<T> list, T obj){
 
 for(int i = 0;i < list.size(); i++){
 if (obj == list.get(i))
 {
 list.remove(obj);
 }
 }
 }

main中调用

<pre name="code" class="java"> 

List<String> list = new ArrayList<>(); 
 list.add("1");
 list.add("2");
 list.add("2");
 list.add("3");
 
 re.forRemove(list,"2");
 System.out.println(list.toString());

程序输出[1,2,3]

这是因为,删除时改变了list的长度。删除第一个2后,长度变为了3,这时list.get(2)为3,不再是2了,不能删除第2个2

2. forEach循环删除

public void forEachRemove(List<T> list, T obj){ 
 for(T item : list){ 
 if (item.equals(obj)) { 
 list.remove(obj); 
 } 
 } 
} 

main方法中:

List<String> list = new ArrayList<>(); 
list.add("1"); 
list.add("2"); 
list.add("2"); 
list.add("3"); 
//re.forRemove(list,"2"); 
re.forEachRemove(list,"2"); 
System.out.println(list.toString());

程序输出:

从运行结果看到程序抛ConcurrentModificationException。

JDK的API中对该异常描述道:

public class ConcurrentModificationException extends RuntimeException当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。

注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。

Java中的For each实际上使用的是iterator进行处理的。而iterator是不允许集合在iterator使用期间删除的。所以导致了iterator抛出了ConcurrentModificationException 。

3. Iterator 迭代器删除(推荐)

public void iteratorRemove(List<T> list, T obj){
 
 Iterator<T> it = list.iterator();
 while(it.hasNext()){
 
 T item = it.next();
 if (item.equals(obj))
 {
 it.remove();//remove the current item
 } 
 }
 }
List<String> list = new ArrayList<>();
 
 list.add("1");
 list.add("2");
 list.add("2");
 list.add("3");
 
 //re.forRemove(list,"2");
 //re.forEachRemove(list,"2");
 re.iteratorRemove(list,"2");
 System.out.println(list.toString());

程序输出:

可以看到这才是真正的删除了我们想删除的元素。但是需要注意以下两点

对Iterator的remove()方法调用必须在Iterator的next()方法之后。

调用next()方法后只能执行一次remove()方法

综上,对于集合的删除操作,特别是List,需要使用迭代器来操作。

补充知识:java中的Collection集合的存入与删除

在java的集合中存储的都是引用类型元素,而且集合只保存每个元素对象的引用,而并非将元素对象本身存入集合。

Collection集合中的remove方法,对于重复元素而言只删除一个

在遍历集合时,若想删除集合里面的元素,只能通过迭代器的删除方法去删除,不能使用集合本身的方法。(这也是为什么在增强for循环中不能使用集合的方法删除元素的原因,因为增强for循环是编译器认可而并不是虚拟机认可。编译器最终会把新循环改编为迭代器循环)

以上这篇java 如何实现正确的删除集合中的元素就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。

 类似资料:
  • 我在Java有一个集合数组列表。 例如,当我这样做时: 测试是集合。 为什么我得到的结果是:[jamesbond] 我只想要jamesbond,但为什么他们也给我[]?

  • 问题内容: AFAIK有两种方法: 遍历集合的副本 使用实际集合的迭代器 例如, 和 是否有任何理由偏爱一种方法(例如,出于可读性的简单原因而偏爱第一种方法)? 问题答案: 让我举几个例子,并提出一些避免方案。 假设我们有以下藏书 收集并删除 第一种技术是收集所有要删除的对象(例如,使用增强的for循环),并在完成迭代后删除所有找到的对象。 假设你要执行的操作是“删除”。 如果要“添加”此方法也可

  • 我有一个列表视图,我正在向其中添加一个上下文菜单。我有“工作查找”上下文菜单,但有另一个问题。 My代码,用于设置上下文菜单: 我的ListView可以通过侦听器通过文本字段进行搜索;当用户键入时,侦听器会过滤列表视图中的项目。 现在的问题是,在筛选列表时,所有空单元格现在都显示为null。 通过阅读另一个问题,我非常确信ListView仍在显示已删除单元格的图形。我知道如何通过重写updateI

  • 对于类中的方法,文档是这样说的: 取消此对话框,将其从屏幕上移除。可以从任何线程安全地调用此方法。请注意,当对话框被取消时,不应重写此方法来进行清理,而应在中实现此方法。 在我的代码中,我所做的就是调用来删除它。但是我没有做其他任何事情,甚至没有使用。因此,我问的是如何正确地删除以避免任何内存泄漏等。

  • 我试图实现的是一个创建/编辑用户工具。可编辑字段有: null null 注意:findAllRolesExceptOwnedByUser()是一个自定义的存储库函数,返回所有角色(那些尚未分配给$User的角色)的子集。 1.3.1添加角色: 1.3.2删除角色: 由于组和角色有相同的问题,我在这里跳过它们。如果我让角色发挥作用,我知道我也能在团队中做到这一点。 没有必要发布这些内容,因为它们工