`

ArratyList 遍历 删除

阅读更多

在工作和学习中,经常碰到删除ArrayList里面的某个元素,看似一个很简单的问题,却很容易出bug。不妨把这个问题当做一道面试题目,我想一定能难道不少的人。今天就给大家说一下在ArrayList循环遍历并删除元素的问题。首先请看下面的例子:

如果要想删除list的b字符,有下面两种常见的错误例子:

错误写法实例一:

错误的原因:这种最普通的循环写法执行后会发现第二个“b”的字符串没有删掉。

错误写法实例二:

错误的原因:这种for-each写法会报出著名的并发修改异常:java.util.ConcurrentModificationException。

先解释一下实例一的错误原因。翻开JDK的ArrayList源码,先看下ArrayList中的remove方法(注意ArrayList中的remove有两个同名方法,只是入参不同,这里看的是入参为Object的remove方法)是怎么实现的:

一般情况下程序的执行路径会走到else路径下最终调用faseRemove方法:

可以看到会执行System.arraycopy方法,导致删除元素时涉及到数组元素的移动。针对错误写法一,在遍历第一个字符串b时因为符合删除条件,所以将该元素从数组中删除,并且将后一个元素移动(也就是第二个字符串b)至当前位置,导致下一次循环遍历时后一个字符串b并没有遍历到,所以无法删除。针对这种情况可以倒序删除的方式来避免:

因为数组倒序遍历时即使发生元素删除也不影响后序元素遍历。

接着解释一下实例二的错误原因。错误二产生的原因却是foreach写法是对实际的Iterable、hasNext、next方法的简写,问题同样处在上文的fastRemove方法中,可以看到第一行把modCount变量的值加一,但在ArrayList返回的迭代器(该代码在其父类AbstractList中):

这里返回的是AbstractList类内部的迭代器实现private class Itr implements Iterator,看这个类的next方法:

第一行checkForComodification方法:

这里会做迭代器内部修改次数检查,因为上面的remove(Object)方法修改了modCount的值,所以才会报出并发修改异常。要避免这种情况的出现则在使用迭代器迭代时(显示或for-each的隐式)不要使用ArrayList的remove,改为用Iterator的remove即可。

分享到:
评论

相关推荐

    遍历删除文件夹下所有文件及目录

    "QT遍历删除文件夹下所有文件及目录" 在QT应用程序中,需要遍历删除文件夹下所有文件及目录是一种常见的操作。本文将详细介绍如何使用QT框架实现该功能。 一、使用QDir和QFileInfo遍历删除文件夹 在QT中,可以...

    一次遍历删除倒数第n个节点

    一次遍历单链表删除倒数第n个节点的问题,跟删除某个节点的前一个节点是一个思路

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

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

    asp遍历文件夹删除多余文件

    asp遍历文件夹删除多余文件,asp遍历文件夹删除多余文件

    数据结构(二叉树的创建 遍历 删除等基本操作)

    本程序旨在通过实现二叉树的创建、遍历、查找以及删除等基本操作,帮助学生深入理解和掌握二叉树的相关知识。 首先,我们要理解什么是二叉树。二叉树是一种特殊的树形数据结构,其中每个节点最多有两个子节点,通常...

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

    如果从头到尾正序遍历删除的话,有些符合删除条件的元素会成为漏网之鱼; 正序删除举例: List<string> tempList = new List() { "a","b","b","c" }; for (int i = 0; i < tempList.Count; i++) { if ...

    二叉树的递归遍历,中序遍历,先序遍历,后序遍历

    二叉树的遍历有多种方式,本文将介绍二叉树的递归遍历,中序遍历,先序遍历和后序遍历。 递归遍历是指使用递归函数来遍历二叉树的每个结点。递归遍历的优点是代码简洁易懂,但缺点是可能会导致堆栈溢出。在本文的...

    二叉树的建立查找遍历删除的实现

    二叉树的建立查找遍历删除的程序的实现,同志们加油

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

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

    二叉树的基本操作,前序遍历,中序遍历,后序遍历,层序遍历

    二叉树的基本操作主要包括创建、插入、删除节点以及遍历等。创建二叉树时,需要指定根节点,之后通过插入操作来构造完整的二叉树结构。删除节点时要考虑节点是否有子节点,以及如何调整树的结构以保持二叉树的特性。...

    图的深度优先遍历和广度优先遍历算法

    "图的深度优先遍历和广度优先遍历算法" 图的深度遍历和广度遍历是两个重要的算法,这也是我们理解并掌握图这一数据结构的基础。通过此程序算法可以进一步掌握图的构造以及遍历的相关知识。 图的深度优先遍历算法 ...

    二叉树先序遍历、中序遍历和后序遍历非递归算法 C++源码

    用C++写的二叉树先序遍历、中序遍历和后序遍历非递归算法

    List集合遍历和删除操作

    List集合遍历和删除操作

    遍历算法遍历方案及几个算法实现

    在二叉树的遍历中,通常有三种主要的遍历方法:前序遍历、中序遍历和后序遍历。这些遍历方式都是基于二叉树的递归定义,即每个节点包含一个值、一个左子节点和一个右子节点。 1. **前序遍历(Preorder Traversal)**...

    Java HashMap 如何正确遍历并删除元素的方法小结

    Java HashMap 遍历和删除元素方法小结 Java HashMap 是一种常用的数据结构,用于存储键值对儿,但是在遍历和删除元素时,需要注意一些特殊的情况,否则可能会出现异常或错误。本文将介绍 Java HashMap 遍历和删除...

    易语言遍历目录文件

    除了基础的遍历,你还可以根据实际需求进行扩展,比如过滤特定类型的文件,或者统计文件数量,甚至对文件进行更复杂的操作,如复制、移动或删除。 在实际开发中,需要注意的是,遍历目录文件时要处理可能出现的错误...

    java数组遍历 删除remove(示例代码)

    如果在遍历过程中删除元素,通常需要使用迭代器(Iterator)来安全地进行,因为迭代器会跟踪当前元素并处理删除后的调整。 最后,输出了ArrayList的大小以及所有学生的姓名、学号和颜色。遍历结束后,输出显示...

    层次遍历先序遍历

    课后作业:层次遍历先序遍历

    二叉树的遍历及通过前序中序遍历确定后序层序遍历

    二叉树的遍历主要有三种经典方法:前序遍历、中序遍历和后序遍历。这些遍历方法是理解二叉树特性和操作的关键。 1. **前序遍历**(Preorder Traversal): - 遵循“根-左-右”的顺序访问节点。首先访问根节点,...

    已知二叉树的前序和中序遍历,打印后序遍历

    对于已知的前序遍历(P遍历)和中序遍历(I遍历),我们可以通过以下步骤打印出后序遍历(H遍历): 1. **初始化**:创建一个空栈,记录当前中序遍历中的位置(初始为0)。 2. **匹配前序遍历**:遍历P遍历,每遇到...

Global site tag (gtag.js) - Google Analytics