双重循环中删除元素怎么做 159次阅读 it • bug及解决方案 2020-08-14 以往操作元素都是在单循环中,很简单也很方便,直到这次,双重循环操作一个集合,外层和内层都需要删除元素,使用简单方法(for)就报错了。 经调查发现必须用**Iterator**才能操作。(对于它的印象还停留在学校学javaSE时的iter.next(),有什么用为什么用忘得一干二净) > 以下是具体业务的进一步步进化以下是具体业务的进一步步进化 ## 初始版本 *造成性能浪费* ``` // 每个人每个群调用一次,性能浪费 for (int i = 0; i < liftList.size(); i++) { List membersAccount2 = new ArrayList<>(); membersAccount2.add(liftList.get(i).getUserId().toString()); tim.forbidSendMsg(liftList.get(i).getGroupId().toString(), membersAccount2, 0); } ``` ## foreach循环版本 *foreach不可删除元素,报错` at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)`* ``` // 遍历所有群 for (ComGroupUserEntity comGroupUser : liftList) { groupId = comGroupUser.getGroupId().toString(); membersAccount.add(comGroupUser.getUserId().toString()); liftList.remove(comGroupUser); // 筛选此群所有人 for (ComGroupUserEntity c2 : liftList) { if (groupId.equals(c2.getGroupId().toString())) { membersAccount.add(c2.getUserId().toString()); liftList.remove(c2); } } log.info("调用tim解除禁言,群 -> {}, 用户集合 -> {}", groupId, membersAccount); tim.forbidSendMsg(groupId, membersAccount, 0); } ``` ## Iterator版本 *单线程可以使用(暂未遇到需要多线程使用的场景,如果需要可能要对Iterator加锁!)* ``` /** 通知tim 解除禁言(优化为根据groupId分组,调用tim) **/ try { String groupId = null; List membersAccount = new ArrayList<>(); while (liftList.iterator().hasNext()) { Iterator iterator = liftList.iterator(); // 遍历所有群 while (iterator.hasNext()) { ComGroupUserEntity aEntity = iterator.next(); groupId = aEntity.getGroupId().toString(); membersAccount.add(aEntity.getUserId().toString()); iterator.remove(); // 筛选此群所有人 while (iterator.hasNext()) { ComGroupUserEntity bEntity = iterator.next(); if (groupId.equals(bEntity.getGroupId().toString())) { membersAccount.add(bEntity.getUserId().toString()); iterator.remove(); } } log.info("调用tim解除禁言,群 -> {}, 用户集合 -> {}", groupId, membersAccount); tim.forbidSendMsg(groupId, membersAccount, 0); membersAccount.clear(); } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ``` 由于两个Iterator循环操作同一个List还是会报错,所以只能是同一个Iterator操作ArrayList,但是这样会造成只循环一次,把第一个群移除后就完成了循环了。所以我在最外面加了一层while循环,保证剩余待处理的结果集被处理干净!😀😀 注意!!Iterator操作元素仅在单线程中是安全的,多线程必须加锁! 参考链接:https://www.cnblogs.com/Joe-Go/p/10419573.html Alipay手机上阅读 最后一次更新于2020-08-14 None
0 条评论