Java自定义集合实现fail-fast机制需维护modCount与expectedModCount版本号同步:集合结构性修改时递增modCount;迭代器构造时记录expectedModCount,并在next()/hasNext()中校验,不等则抛ConcurrentModificationException;迭代器remove()后须同步更新expectedModCount。

Java 中自定义集合要实现 fail-fast 迭代失效机制,核心是模拟 ArrayList 等标准集合的 modCount + expectedModCount 校验逻辑。它不是靠魔法,而是靠迭代器与集合本体之间约定好的“版本号同步”机制。
关键字段:维护 modCount 计数器
在自定义集合类中,需声明一个 protected transient int modCount = 0 字段(建议用 transient,避免序列化干扰)。每次发生结构性修改(如 add、remove、clear、retainAll、removeAll 等改变元素数量或底层结构的操作),都必须手动递增 modCount++。
- 注意:仅结构性修改才触发,比如
set(index, e)替换值不改结构,一般不加modCount - 若继承
AbstractList或AbstractCollection,可复用其已有的modCount和校验逻辑
迭代器内部:保存并校验版本号
自定义迭代器(如 MyIterator)需在构造时读取当前 modCount,存为自己的 expectedModCount 字段:
- 在
hasNext()或next()开头调用校验方法(如checkForComodification()) - 校验逻辑很简单:
if (modCount != expectedModCount) throw new ConcurrentModificationException(); - 若迭代器自身提供
remove()方法,执行后必须同步更新expectedModCount = modCount,否则下次调用next()仍会失败
确保迭代器由集合统一创建
集合必须通过 iterator() 方法返回迭代器实例,且该方法中完成 expectedModCount 的初始化。不能允许用户绕过集合直接 new 迭代器,否则版本号无法对齐。
立即学习“Java免费学习笔记(深入)”;
- 推荐将迭代器设为私有内部类,绑定外部集合实例
- 避免 public 构造器暴露迭代器创建细节
- 如果支持
ListIterator,同样需在listIterator()中初始化对应版本号
单线程合法修改:迭代器自身的 remove() 必须同步计数
这是 fail-fast 不报错的唯一“例外”,也是设计意图所在——允许迭代中安全删除当前元素。因此:
-
MyIterator.remove()执行集合删除操作后,必须立即更新expectedModCount = modCount - 否则即使调用的是迭代器方法,下一次
next()仍会因版本不匹配而抛异常 - 这个同步动作,正是区分“合法迭代内修改”和“非法外部修改”的关键


















