`

正确在遍历中删除List元素

    博客分类:
  • JAVA
 
阅读更多

一般而言,遍历List元素有以下三种方式:

 

  • 使用普通for循环遍历
  • 使用增强型for循环遍历
  • 使用iterator遍历

使用普通for循环遍历

代码如下:
[java] view plain copy
 
  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         List<Integer> list = new ArrayList<>();  
  4.         for (int i = 0; i < 5; i++)  
  5.             list.add(i);  
  6.         // list {0, 1, 2, 3, 4}  
  7.         for (int i = 0; i < list.size(); i++) {  
  8.             // index and number  
  9.             System.out.print(i + " " + list.get(i));  
  10.             if (list.get(i) % 2 == 0) {  
  11.                 list.remove(list.get(i));  
  12.                 System.out.print(" delete");  
  13.                 i--; // 索引改变!  
  14.             }  
  15.             System.out.println();  
  16.         }  
  17.     }  
  18. }  

结果如下:
普通for循环遍历
 
可以看到遍历删除偶数的结果是成功的,但是这种方法由于删除的时候会改变list的index索引和size大小,可能会在遍历时导致一些访问越界的问题,因此不是特别推荐。
 

使用增强型for循环遍历

[java] view plain copy
 
  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         List<Integer> list = new ArrayList<>();  
  4.         for (int i = 0; i < 5; i++)  
  5.             list.add(i);  
  6.         // list {0, 1, 2, 3, 4}  
  7.         for (Integer num : list) {  
  8.             // index and number  
  9.             System.out.print(num);  
  10.             if (num % 2 == 0) {  
  11.                 list.remove(num);  
  12.                 System.out.print(" delete");  
  13.             }  
  14.             System.out.println();  
  15.         }  
  16.     }  
  17. }  

结果如下:
增强for循环遍历
 
可以看到删除第一个元素时是没有问题的,但删除后继续执行遍历过程的话就会抛出ConcurrentModificationException的异常。
 

使用iterator遍历

[java] view plain copy
 
  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         List<Integer> list = new ArrayList<>();  
  4.         for (int i = 0; i < 5; i++)  
  5.             list.add(i);  
  6.         // list {0, 1, 2, 3, 4}  
  7.         Iterator<Integer> it = list.iterator();  
  8.         while (it.hasNext()) {  
  9.             // index and number  
  10.             int num = it.next();  
  11.             System.out.print(num);  
  12.             if (num % 2 == 0) {  
  13.                 it.remove();  
  14.                 System.out.print(" delete");  
  15.             }  
  16.             System.out.println();  
  17.         }  
  18.     }  
  19. }  

结果如下:
iterator循环遍历
 
可以看到顺利的执行了遍历并删除的操作,因此最推荐的做法是使用iterator执行遍历删除操作。
 
以上是关于非线程安全的ArrayList,如果是线程安全的CopyOnWriteArrayList呢?
 

使用普通for循环遍历

 
[java] view plain copy
 
  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         List<Integer> list = new CopyOnWriteArrayList<>();  
  4.         for (int i = 0; i < 5; i++)  
  5.             list.add(i);  
  6.         // list {0, 1, 2, 3, 4}  
  7.         for (int i = 0; i < list.size(); i++) {  
  8.             // index and number  
  9.             System.out.print(i + " " + list.get(i));  
  10.             if (list.get(i) % 2 == 0) {  
  11.                 list.remove(list.get(i));  
  12.                 System.out.print(" delete");  
  13.                 i--; // 索引改变!  
  14.             }  
  15.             System.out.println();  
  16.         }  
  17.     }  
  18. }  

结果如下:
CopyOnWriteArrayList遍历删除
可以看到遍历删除是成功的,但是这种方法由于删除的时候会改变list的index索引和size大小,可能会在遍历时导致一些访问越界的问题,因此不是特别推荐。
 

使用增强型for循环遍历

[java] view plain copy
 
  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         List<Integer> list = new CopyOnWriteArrayList<>();  
  4.         for (int i = 0; i < 5; i++)  
  5.             list.add(i);  
  6.         // list {0, 1, 2, 3, 4}  
  7.         for (Integer num : list) {  
  8.             // index and number  
  9.             System.out.print(num);  
  10.             if (num % 2 == 0) {  
  11.                 list.remove(num);  
  12.                 System.out.print(" delete");  
  13.             }  
  14.             System.out.println();  
  15.         }  
  16.     }  
  17. }  

结果如下:
CopyOnWriteArrayList增强for遍历删除
 
可以看见与ArrayList遍历删除时情况不同,CopyOnWriteArrayList是允许使用增强型for进行循环遍历删除的。
 

使用iterator遍历

[java] view plain copy
 
  1. public class Main {  
  2.     public static void main(String[] args) throws Exception {  
  3.         List<Integer> list = new CopyOnWriteArrayList<>();  
  4.         for (int i = 0; i < 5; i++)  
  5.             list.add(i);  
  6.         // list {0, 1, 2, 3, 4}  
  7.         Iterator<Integer> it = list.iterator();  
  8.         while (it.hasNext()) {  
  9.             // index and number  
  10.             int num = it.next();  
  11.             System.out.print(num);  
  12.             if (num % 2 == 0) {  
  13.                 it.remove();  
  14.                 System.out.print(" delete");  
  15.             }  
  16.             System.out.println();  
  17.         }  
  18.     }  
  19. }  

结果如下:
CopyOnWriteArrayList的iterator遍历删除
 
与ArrayList不同,由于CopyOnWriteArrayList的iterator是对其List的一个“快照”,因此是不可改变的,所以无法使用iterator遍历删除。
 
综上所述,当使用ArrayList时,我们可以使用iterator实现遍历删除;而当我们使用CopyOnWriteArrayList时,我们直接使用增强型for循环遍历删除即可,此时使用iterator遍历删除反而会出现问题。

 

分享到:
评论

相关推荐

    C#遍历List并删除某个元素的方法

    当我们需要遍历List并根据条件删除特定元素时,需要注意正确的方法,以避免在遍历过程中出现错误。以下将详细介绍如何在C#中遍历List并删除元素,包括正序和倒序遍历的技巧。 首先,我们来看一下错误的遍历方式。...

    C++ STL list 遍历删除出错解决方案

    本篇文章主要探讨的是在使用STL list时遇到的遍历删除元素过程中常见的错误及其解决方案。 错误用法通常出现在尝试同时遍历和删除list中的元素时。以下是三种常见的错误做法: 1. 错误用法一: 在这个例子中,迭代...

    正确遍历删除List中的元素方法(推荐)

    以下是几种常见的遍历删除List元素的方法及其注意事项: 1. **通过增强的for循环删除元素** - **问题**:在增强的for循环(foreach)中直接删除元素会导致`ConcurrentModificationException`,因为这种方式不允许...

    HashMap和List遍历方法及如何遍历删除元素总结

    HashMap和List遍历方法及如何遍历删除元素总结 HashMap和List都是Java中最常用的数据结构,它们都可以用来存储和操作数据。然而,在遍历和删除元素时,需要小心地处理,以免出现问题。下面总结了HashMap和List的...

    java中循环遍历删除List和Set集合中元素的方法(推荐)

    在Java编程中,遍历并删除集合(如List或Set)中的元素是一项常见的操作,但如果不正确地执行,可能会导致`ConcurrentModificationException`异常。这个异常通常在尝试修改正在迭代的集合时出现,因为Java的集合迭代...

    Iterator遍历过程中list删除导致异常

    在Java编程中,`Iterator`是用于遍历集合(如`List`, `Set`等)的重要工具。然而,当我们尝试在使用`Iterator`遍历集合的过程中直接修改集合时,可能会遇到`ConcurrentModificationException`异常。这个异常通常发生...

    Java如何在List或Map遍历过程中删除元素

    在Java编程中,遍历并删除List或Map中的元素是一个常见的任务,但如果不理解其内部机制,可能会导致一些未预期的问题。本文将深入探讨在Java中如何安全地在List和Map遍历过程中删除元素。 首先,我们来看List的遍历...

    C#在foreach遍历删除集合中元素的三种实现方法

    C#在foreach遍历删除集合中元素的三种实现方法 C#中,foreach遍历删除集合中元素是很常见的操作,但是删除元素时,集合的大小和元素索引值会发生变化,从而导致在foreach中删除元素时会抛出异常。下面我们将介绍三...

    C#集合遍历时删除和增加元素的方法

    总结起来,处理C#集合遍历过程中的元素修改,特别是删除和增加操作,需要使用支持在遍历中修改的集合类型,如`LinkedList&lt;T&gt;`,并且在操作过程中需要特别注意元素引用的更新,以避免数据丢失或遍历错误。在实际编程...

    Python中list循环遍历删除数据的正确方法

    前言 初学Python,遇到过这样的问题,在遍历list的时候,删除符合条件的数据,可是总是报异常,代码如下: ...原因是在删除list中的元素后,list的实际长度变小了,但是循环次数没有减少,依然按照

    66丨迭代器模式(中):遍历集合的同时,为什么不能增删集合元素?1

    为了解决这个问题,Java中的`List`接口提供了`remove()`方法的另一种版本——`Iterator.remove()`,这个方法可以安全地在遍历过程中删除当前元素。这是因为迭代器在调用`remove()`时,会更新自身的状态以反映元素已...

    【Java面试题】List如何一边遍历,一边删除?

    在Java编程中,遍历并删除List集合是一个常见的操作,但在实际编程中,如果不使用正确的方法,可能会导致`java.util.ConcurrentModificationException`异常。本文主要针对这个面试题,详细讲解如何在遍历List的同时...

    解决JAVA遍历List集合,删除数据时出现的问题

    在遍历List集合时,我们可以使用for循环来删除元素,但是我们需要注意的是,在删除元素后,我们需要将迭代变量i的值减1,以便在下一次迭代中处理正确的元素。 解决方法2:先删除后面的元素 另一种解决方法是,先...

    完美解决python遍历删除字典里值为空的元素报错问题

    通过上述内容的学习,我们可以了解到在 Python 中如何正确地遍历并删除字典中的元素,避免常见的运行时错误,并理解了字典视图对象的特性和使用方法。这对于日常开发中处理字典数据非常有帮助。

    C#遍历集合与移除元素的方法

    在C#编程中,遍历集合和移除元素是常见的操作,尤其在处理大量数据时。本篇文章将详细讲解如何使用C#有效地遍历集合并安全地移除元素,同时提供一些最佳实践。 首先,我们要了解C#中的两种主要遍历集合的方式:`for...

    python列表的逆序遍历实现

    例如,在一个包含数字的列表中,如果我们要删除所有包含数字"2"的元素,直接正向遍历并使用`remove()`函数会遇到问题,因为删除元素会导致后续元素的下标发生变化,使得某些元素在遍历过程中被遗漏。 错误的正向...

    java-遍历map

    - 在遍历`Map`时,如果在遍历过程中尝试修改`Map`(例如添加或删除元素),可能会引发`ConcurrentModificationException`异常。因此,在遍历的同时不要修改`Map`。 - 使用流API遍历时,虽然代码更简洁,但性能上可能...

    对python list 遍历删除的正确方法详解

    初学者往往会直接在遍历过程中使用.pop()方法删除元素,这通常会导致程序报错,例如“IndexError: list index out of range”。原因是删除元素后,列表的长度发生了改变,但是循环次数没有相应减少,导致索引与列表...

    Java list利用遍历进行删除操作3种方法解析

    这个示例中,会出现下标问题,因为在删除元素后,list 的大小发生了变化,导致下标的计算不正确。为了解决这个问题,可以使用倒序操作,避免下标问题: ```java int size = list.size(); for (int i = size - 1; i ...

Global site tag (gtag.js) - Google Analytics