Java对比enum与List提取非枚举值遇ConcurrentModificationException如何解决
报错原因
- 你在使用增强for循环遍历
enumValues集合的同时,直接调用了List.remove()方法修改集合结构。增强for循环底层基于迭代器实现,迭代器遍历过程中如果集合结构被外部修改(不是迭代器自身的remove方法),就会抛出ConcurrentModificationException异常。 - 另外你的业务逻辑也写反了:需求是返回「汽车列表中存在但不在Brand枚举范围内的元素」,但你现有逻辑是删除
enumValues里和cars重复的元素,最终返回的是「枚举中存在但汽车列表里没有的元素」,完全不符合需求。 - 你的代码还存在笔误:遍历
Brand.values()时,变量类型写的是ProductCategory,应该改为Brand。
正确实现方案
推荐先把枚举合法值转成Set,利用Set的O(1)查找效率快速判断元素是否合法,全程不需要修改原集合,不会触发并发修改异常:
普通循环写法
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public List<String> extractInvalidCars(List<String> cars) { // 提取所有合法的枚举品牌名存入Set Set<String> validBrands = Arrays.stream(Brand.values()) .map(Enum::name) .collect(Collectors.toSet()); List<String> invalidCars = new ArrayList<>(); // 遍历汽车列表,筛选不在合法集合中的元素 for (String car : cars) { if (!validBrands.contains(car)) { invalidCars.add(car); } } return invalidCars; }
Java 8+ 流式简化写法
public List<String> extractInvalidCars(List<String> cars) { Set<String> validBrands = Arrays.stream(Brand.values()) .map(Enum::name) .collect(Collectors.toSet()); return cars.stream() .filter(car -> !validBrands.contains(car)) .collect(Collectors.toList()); }
调用该方法传入你初始化的汽车列表,返回结果就是["CHRYSLER", "SKODA", "PORSCHE"],符合你的需求。
原有写法的异常修复方案
如果你坚持要基于你原有逻辑修改,遍历删除元素时要使用迭代器的remove()方法,同时修正逻辑:
public List<String> extractInvalidCars(List<String> cars) { List<String> enumValues = new ArrayList<>(); for (Brand enumBrand: Brand.values()) { enumValues.add(String.valueOf(enumBrand)); } List<String> invalidCars = new ArrayList<>(cars); // 使用迭代器删除合法元素,剩下的就是非法元素 Iterator<String> iterator = invalidCars.iterator(); while (iterator.hasNext()) { String car = iterator.next(); if (enumValues.contains(car)) { iterator.remove(); } } return invalidCars; }
内容的提问来源于stack exchange,提问作者Mannual
相关产品推荐
相关产品推荐

