面试题:在迭代一个集合的时候,如何避免 ConcurrentModificationException ?

ConcurrentModificationException 是 Java 集合框架中常见的异常,通常发生在使用迭代器遍历集合时,集合的结构被修改(例如添加、删除元素),但未通过迭代器本身进行修改。为了避免该异常,可以采取以下方法:


1. 使用迭代器的 remove() 方法

  • 在遍历集合时,如果需要删除元素,应该使用迭代器提供的 remove() 方法,而不是直接调用集合的 remove() 方法。
  • 示例:
    List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        if ("B".equals(item)) {
            iterator.remove(); // 使用迭代器的 remove() 方法
        }
    }

2. 使用并发集合类

  • 如果需要在多线程环境下修改集合,可以使用 java.util.concurrent 包中的并发集合类,如 CopyOnWriteArrayListConcurrentHashMap 等。
  • 这些集合类在设计上支持并发修改,不会抛出 ConcurrentModificationException
  • 示例:
    List<String> list = new CopyOnWriteArrayList<>(Arrays.asList("A", "B", "C"));
    for (String item : list) {
        if ("B".equals(item)) {
            list.remove(item); // 安全操作
        }
    }

3. 遍历时避免直接修改集合

  • 如果需要修改集合,可以先记录需要修改的内容,遍历结束后再统一修改。
  • 示例:
    List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
    List<String> toRemove = new ArrayList<>();
    for (String item : list) {
        if ("B".equals(item)) {
            toRemove.add(item); // 记录需要删除的元素
        }
    }
    list.removeAll(toRemove); // 遍历结束后统一删除

4. 使用传统的 for 循环

  • 如果需要通过索引修改集合,可以使用传统的 for 循环,但需要注意索引的正确性。
  • 示例:
    List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
    for (int i = 0; i < list.size(); i++) {
        if ("B".equals(list.get(i))) {
            list.remove(i); // 直接通过索引删除
            i--; // 调整索引
        }
    }

5. 使用 Stream API(Java 8+)

  • 使用 Stream 的 filter() 方法可以避免直接修改集合。
  • 示例:
    List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
    list = list.stream()
               .filter(item -> !"B".equals(item))
               .collect(Collectors.toList());

总结:

避免 ConcurrentModificationException 的关键在于:

  • 使用迭代器的 remove() 方法修改集合。
  • 使用并发集合类(如 CopyOnWriteArrayList)。
  • 遍历时避免直接修改集合,或者使用其他方法(如 Stream)间接操作集合。
THE END
点赞9 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容