MST

星途 面试题库

面试题:Java迭代器的fail - fast机制

请详细阐述Java集合框架中迭代器的fail - fast机制。它是如何实现的?在哪些集合类中存在这种机制?当发生fail - fast时会有什么表现?请结合代码示例说明如何触发和处理fail - fast情况。
15.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. fail - fast机制概述

Fail - fast机制是Java集合框架中的一种错误检测机制。当在迭代一个集合的过程中,该集合的结构被意外修改(非通过迭代器自身的remove()方法)时,迭代器会快速抛出ConcurrentModificationException异常,而不是继续迭代并产生不确定的结果。

2. 实现原理

  • modCount变量:在集合类(如ArrayListHashMap等)中,存在一个modCount变量,用于记录集合结构被修改的次数。每次集合结构发生改变(如添加、删除元素等操作),modCount的值就会增加。
  • 迭代器的expectedModCount:迭代器在创建时,会将集合的modCount值赋给自身的expectedModCount变量。在迭代过程中,每次调用next()remove()方法时,迭代器都会检查modCountexpectedModCount是否相等。如果不相等,就认为集合结构被意外修改,抛出ConcurrentModificationException异常。

3. 存在该机制的集合类

  • List接口实现类:如ArrayListLinkedList
  • Set接口实现类:如HashSetTreeSet
  • Map接口实现类:如HashMapTreeMap

4. fail - fast发生时的表现

当在迭代过程中集合结构被意外修改,下次调用迭代器的next()remove()方法时,会立即抛出ConcurrentModificationException异常,迭代过程终止。

5. 代码示例

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class FailFastExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("cherry");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
            // 尝试在迭代过程中修改集合结构,不通过迭代器的remove()方法
            list.add("date"); 
        }
    }
}

在上述代码中,在迭代list的过程中,调用list.add("date")修改了集合结构,当再次调用iterator.next()时,就会触发fail - fast机制,抛出ConcurrentModificationException异常。

6. 处理fail - fast情况

  • 使用迭代器的remove()方法:在迭代过程中,如果需要删除元素,应该使用迭代器的remove()方法,这样modCountexpectedModCount会同步更新,不会触发fail - fast
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class HandleFailFastExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("cherry");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            if ("banana".equals(element)) {
                iterator.remove(); 
            }
        }
        System.out.println(list); 
    }
}
  • 使用线程安全的集合类:如CopyOnWriteArrayListConcurrentHashMap等,这些集合类采用了不同的机制(如写时复制等)来保证线程安全,不会触发fail - fast
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class ThreadSafeCollectionExample {
    public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("cherry");

        for (String element : list) {
            System.out.println(element);
            list.add("date"); 
        }
        System.out.println(list); 
    }
}

CopyOnWriteArrayList中,迭代器不会抛出ConcurrentModificationException,因为它在迭代时使用的是集合的一个快照,修改操作会在新的数组上进行。