Map迭代过程中remove引发的java.util.concurrentmodificationexception

唉,基础还是不过硬,又在博客记录下一个小问题的解决思路。先贴出出错的代码,大家看看哪里会出问题:

      

[java]  view plain copy print ?
  1. // 定义的一个map常量  
  2. private static final Map<AlarmInfo, String> PLAN_ALARM_MAP = new LinkedHashMap<AlarmInfo, String>();  
  3.   
  4. // 下面是处理过程  
  5. synchronized (PLAN_ALARM_MAP) {  
  6.                         logger.infoT("PLAN_ALARM_MAP size " + PLAN_ALARM_MAP.size());  
  7.             Set<AlarmInfo> set = PLAN_ALARM_MAP.keySet();  
  8.                         for (AlarmInfo alarmInfo : set) {  
  9.                 if (!checkContinueAlarm(alarmInfo,  
  10.                         PLAN_ALARM_MAP.get(alarmInfo))) {  
  11.                     logger.infoT("clear planTask alarm!");  
  12.                     // 清除告警信息  
  13.                     manageAlarm(alarmInfo, mesg, true);  
  14.   
  15.                     PLAN_ALARM_MAP.remove(alarmInfo);  
  16.                     // 记录下来,后面删除  
  17.                     // alarmDelete.add(alarmInfo);  
  18.                 }  
  19.             }  
  20. }  

         看出来了吧,和List一样,在循环迭代过程中是不能修改或者删除Map的key的,会引发java.util.concurrentmodificationexception,很有趣的是,就像api说的,在大部分情况下会引起该异常,但有时候不会出异常,至于这个原因没深入研究源码,就暂且不论。发现了异常,就要满足在循环迭代Map的keySet的过程中删除map中的符合条件key的别的解决办法,在网上查了下找到两套都能实现的办法:

          1 将要删除的key存到一个List中,在遍历完map的keySet后,再迭代这个存放删除key的List,逐一删除!

          2 采用Iterator迭代,在迭代遇到需要删除的key时,采用迭代器的remove()方法删除,也可以避免出现异常!

          方案1的解决代码如下:

         

[java]  view plain copy print ?
  1. private static final Map<AlarmInfo, String> PLAN_ALARM_MAP = new LinkedHashMap<AlarmInfo, String>();  
  2.   
  3. synchronized (PLAN_ALARM_MAP) {  
  4.   
  5.             logger.infoT("PLAN_ALARM_MAP size " + PLAN_ALARM_MAP.size());  
  6.             Set<AlarmInfo> set = PLAN_ALARM_MAP.keySet();  
  7.             List<AlarmInfo> alarmDelete = new ArrayList<AlarmInfo>();  
  8.   
  9.             for (AlarmInfo alarmInfo : set) {  
  10.                 if (!checkContinueAlarm(alarmInfo,  
  11.                         PLAN_ALARM_MAP.get(alarmInfo))) {  
  12.                     logger.infoT("clear planTask alarm!");  
  13.                     // 清除告警信息  
  14.                     manageAlarm(alarmInfo, mesg, true);  
  15.   
  16.   
  17.                     // 记录下来,后面删除  
  18.                     alarmDelete.add(alarmInfo);  
  19.                 }  
  20.             }  
  21.   
  22.              // 进行删除   
  23.              for (AlarmInfo deleteAlarm : alarmDelete) {  
  24.                   PLAN_ALARM_MAP.remove(deleteAlarm);  
  25.              }  
  26.         }  
             方案2代码如下:

            

[java]  view plain copy print ?
  1. private static final Map<AlarmInfo, String> PLAN_ALARM_MAP = new LinkedHashMap<AlarmInfo, String>();  
  2.   
  3. synchronized (PLAN_ALARM_MAP) {  
  4.   
  5.             logger.infoT("PLAN_ALARM_MAP size " + PLAN_ALARM_MAP.size());  
  6.             Set<AlarmInfo> set = PLAN_ALARM_MAP.keySet();  
  7.   
  8.             AlarmInfo tempAlarmInfo = null;  
  9.             for (Iterator<AlarmInfo> itr = set.iterator(); itr.hasNext();) {  
  10.   
  11.                 tempAlarmInfo = itr.next();  
  12.                 if (!checkContinueAlarm(tempAlarmInfo,  
  13.                         PLAN_ALARM_MAP.get(tempAlarmInfo))) {  
  14.                     logger.infoT("clear planTask alarm!");  
  15.                     // 清除告警信息  
  16.                     manageAlarm(tempAlarmInfo, mesg, true);  
  17.                     itr.remove();  
  18.                 }  
  19.             }  
  20.         }  

                 参考文献:

                 http://yulimeander.i.sohu.com/blog/view/142269299.htm

                 http://swincle.iteye.com/blog/746980

                 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值