深入剖析遍历 List 时删除元素的微妙影响
2023-11-29 04:19:01
当我们遍历一个 List 时,有时可能会遇到需要删除元素的情况。然而,在遍历过程中执行删除操作可能会导致意料之外的后果,因此了解其背后的机制至关重要。
在 Java 中,List 是一种有序的集合,它允许重复元素。遍历 List 的常用方式是使用迭代器(例如 for-each 循环或迭代器本身),它提供了逐个访问 List 中元素的能力。
fail-fast 机制
Java 集合框架采用了一种称为 "fail-fast" 的机制,当对正在遍历的集合进行结构性修改(例如添加或删除元素)时,该机制会抛出一个 ConcurrentModificationException
。这是为了确保集合的完整性,因为遍历期间的修改可能会导致不可预测的结果。
遍历 List 时删除元素的后果
当我们在遍历 List 时删除一个元素,fail-fast 机制就会被触发,抛出一个 ConcurrentModificationException
。这是因为删除操作从 List 中删除了一个元素,从而改变了集合的结构。
<#sub-title>理解 fail-fast 机制的原理</#sub-title>
fail-fast 机制是通过在每个集合上维护一个 modCount
变量来实现的。每当集合的结构发生变化时(例如添加或删除元素),modCount 就会增加。迭代器在创建时会记录集合的当前 modCount,并在每次迭代时对其进行比较。
如果迭代器检测到集合的 modCount 与其记录的 modCount 不匹配,则会抛出一个 ConcurrentModificationException
,表示集合在遍历期间已被修改。
<#sub-title>遍历 List 时安全删除元素的方法</#sub-title>
虽然在遍历 List 时删除元素可能会导致错误,但有几种方法可以安全地实现这一操作:
使用迭代器本身进行删除
可以使用迭代器本身删除元素,方法是调用 remove()
方法。这种方法不会触发 fail-fast 机制,因为迭代器会自动更新其 modCount。
使用 removeIf()
方法
removeIf()
方法接受一个谓词(一个返回布尔值的函数),并删除满足谓词条件的所有元素。此方法是安全地从 List 中删除元素的另一个选择,因为它不会触发 fail-fast 机制。
使用 ListIterator
ListIterator
提供了一个 remove()
方法,可以安全地从 List 中删除元素。与 removeIf()
方法类似,remove()
方法也不会触发 fail-fast 机制。
<#sub-title>结论</#sub-title>
在遍历 List 时删除元素会触发 fail-fast 机制,这是为了确保集合的完整性。通过理解这一机制,我们可以安全地执行删除操作,避免并发修改异常。