在onPostExecute()遍历ArrayList模型触发ConcurrentModificationException问题
解决遍历ArrayList时触发ConcurrentModificationException的问题
首先,咱们先搞清楚为什么会出现这个异常:你用**增强for循环(for-each)**遍历Items的时候,直接调用Items.add()修改集合,这触发了ArrayList的「快速失败」机制。ArrayList的迭代器在遍历过程中,会检测集合是否被结构性修改(比如add/remove这类操作),如果发现就会抛出这个异常,防止并发修改导致的数据不一致。
另外,你的去重逻辑也存在问题:现在的写法会导致同一个元素被多次添加——比如当Items里已有多个元素时,只要其中一个元素的id不匹配当前id,就会执行一次add,最终同一个id可能被重复添加好几次。
下面给你几个可行的解决方案,以及修正后的去重逻辑:
方案1:用普通索引循环代替增强for循环
普通for循环不依赖迭代器,直接通过索引访问元素,所以可以安全地在循环中修改集合。同时先修正去重逻辑:先检查整个集合里是否存在目标id,不存在再添加。
JSONArray data = obj.getJSONArray("response"); for (int i = 0; i < data.length(); i++) { String id = data.getJSONObject(i).optString("id"); boolean isExist = false; // 先检查Items中是否已存在该id for (int j = 0; j < Items.size(); j++) { TrackingModel item = Items.get(j); if (item.id().toString().contains(id)) { isExist = true; break; } } // 如果不存在,再添加 if (!isExist) { TrackingModel reg = new TrackingModel(); reg.setId(id); // 这里可以安全添加 Items.add(reg); } }
方案2:使用迭代器的add方法
ArrayList的迭代器支持add方法,用它来添加元素不会触发异常,同时也能保证遍历的正确性:
JSONArray data = obj.getJSONArray("response"); for (int i = 0; i < data.length(); i++) { String id = data.getJSONObject(i).optString("id"); boolean isExist = false; Iterator<TrackingModel> iterator = Items.iterator(); while (iterator.hasNext()) { TrackingModel item = iterator.next(); if (item.id().toString().contains(id)) { isExist = true; break; } } if (!isExist) { TrackingModel reg = new TrackingModel(); reg.setId(id); // 这里不在迭代器遍历的循环内修改,直接用Items.add即可 Items.add(reg); } }
方案3:先收集待添加元素,遍历完成后批量添加
这种方式更高效,尤其是当集合元素较多时,能减少多次修改集合的开销:
JSONArray data = obj.getJSONArray("response"); List<TrackingModel> newItems = new ArrayList<>(); for (int i = 0; i < data.length(); i++) { String id = data.getJSONObject(i).optString("id"); boolean isExist = false; for (TrackingModel item : Items) { if (item.id().toString().contains(id)) { isExist = true; break; } } if (!isExist) { TrackingModel reg = new TrackingModel(); reg.setId(id); newItems.add(reg); } } // 遍历完成后批量添加到原集合 Items.addAll(newItems);
关于你问的外部方法
其实不需要专门写外部方法,只要解决遍历和修改的冲突问题就行。当然如果后续逻辑复杂,把添加元素的逻辑抽成外部方法是可以的,但核心还是要避免在遍历迭代器的时候直接修改集合。
另外,给你个优化建议:如果id是唯一标识,你可以用HashSet来存储已有的id,这样检查是否存在的效率会从O(n)降到O(1),比如:
Set<String> existingIds = new HashSet<>(); // 先把已有id存入Set for (TrackingModel item : Items) { existingIds.add(item.id().toString()); } JSONArray data = obj.getJSONArray("response"); for (int i = 0; i < data.length(); i++) { String id = data.getJSONObject(i).optString("id"); if (!existingIds.contains(id)) { TrackingModel reg = new TrackingModel(); reg.setId(id); Items.add(reg); existingIds.add(id); } }
这样不仅避免了异常,还大幅提升了去重的效率。
内容的提问来源于stack exchange,提问作者BENN1TH
相关产品推荐
相关产品推荐

