如何避免代码中的ConcurrentModificationException?



  之前说每周坚持更新一篇博客,不管什么类型的都好,但自己还是没能做到,不过从这周开始我会坚持每周至少更新一篇博客!说到做到!

  相信大家在编写java代码时,一个稍不留神就会触发到ConcurrentModificationException,直译过来也就是并发修改异常,那么什么样的情况会导致这种异常抛出呢?我在这周上班时就遇到过了,首先先来一段我写的代码,如下所示:
public static List<String> filterData(List<String> originList, List<String> targetList){
        if (CollUtil.isNotEmpty(originList) && CollUtil.isNotEmpty(targetList)){
            originList.forEach(origin ->{
                targetList.forEach(target ->{
                    if (target.equals(origin)){
                        originList.remove(origin);
                    }
                });
        }
        return originList;
    }

  大家可以看出上面的代码还是有一定的问题的,经过分析,可以看到我在遍历originList的同时又去对originList的内容进行remove,这样会容易触发到集合类中的 fail-fast(快速失败)机制,直接抛出了ConcurrentModificationException这个异常,网上有一段资料对这个异常描述得还是挺到位的,我贴出来给大家看下:

Essentially, the ConcurrentModificationException is used to fail-fast when something we are iterating on is modified.

  从字面意思上就可以很容易明白,如果在遍历迭代比如集合中的数据的同时,你又去篡改集合里面的数据,这就会触发ConcurrentModificationException这个异常,以此来响应这个集合类中的快速失败机制。
  原因我们已经明白了,那么我们如何解决呢?网上有些资料说可以使用一些线程安全的集合类,比如CopyOnWriteArrayList等等来替代ArrayList,但我使用了一个更好的方法,话不多说,我先贴出我修改后的代码:

public static List<String> filterData(List<String> originList, List<String> targetList){
        if (CollUtil.isNotEmpty(originList) && CollUtil.isNotEmpty(targetList)){
            targetList.forEach(target ->{
                originList.removeIf(origin -> origin.equals(target));
            });
        }
        return originList;
    }

  大家通过比较可以看出,我直接不同这么麻烦在外围遍历originList,而是以functional programming(函数式编程)的方式来轻松解决这个问题。分析removeIf里面的源码,我发现里面就是使用Iterator的方式来实现的,这样确保了在遍历originList的同时删除特定元素的安全性,大家有兴趣的话可以分析下里面的源码。
  那么除了上述我说的方法之外,还有其它方法吗?当然有!这里我贴出一个网址,这个网址里面就针对ConcurrentModificationException列出了不同的剖解决方案,还是不错的!
Avoiding the ConcurrentModificationException in Java
还有一个csdn博客对于这个异常产生原因的分析得比我还更深入,大家不妨也看一下。
ConcurrentModificationException产生原因及解决方法


  好的,今天就讲这么多,希望我能帮助到大家,谢谢!如果我有说得不对的地方,希望大家踊跃提出来!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Melo_FengZhi

您的鼓励对我就是巨大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值