面试题答案
一键面试1. fail - fast机制概述
Fail - fast机制是Java集合框架中的一种错误检测机制。当在迭代一个集合的过程中,该集合的结构被意外修改(非通过迭代器自身的remove()方法)时,迭代器会快速抛出ConcurrentModificationException
异常,而不是继续迭代并产生不确定的结果。
2. 实现原理
- modCount变量:在集合类(如
ArrayList
、HashMap
等)中,存在一个modCount
变量,用于记录集合结构被修改的次数。每次集合结构发生改变(如添加、删除元素等操作),modCount
的值就会增加。 - 迭代器的expectedModCount:迭代器在创建时,会将集合的
modCount
值赋给自身的expectedModCount
变量。在迭代过程中,每次调用next()
或remove()
方法时,迭代器都会检查modCount
和expectedModCount
是否相等。如果不相等,就认为集合结构被意外修改,抛出ConcurrentModificationException
异常。
3. 存在该机制的集合类
- List接口实现类:如
ArrayList
、LinkedList
。 - Set接口实现类:如
HashSet
、TreeSet
。 - Map接口实现类:如
HashMap
、TreeMap
。
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()
方法,这样modCount
和expectedModCount
会同步更新,不会触发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);
}
}
- 使用线程安全的集合类:如
CopyOnWriteArrayList
、ConcurrentHashMap
等,这些集合类采用了不同的机制(如写时复制等)来保证线程安全,不会触发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
,因为它在迭代时使用的是集合的一个快照,修改操作会在新的数组上进行。