瞧瞧bug

1. 问题代码段描述

List<Obj> objList = ObjUtil.getObjList();
if(null != objList && !objList.isEmpty()){
    for(Obj p :objList){
        if(p.getCode().equals(str)){
            objList.remove(p);
        }
     }
}

 

2.bug描述

   遇到了如下Exception:

Caused by: java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)

 

3.问题描述

    这个错误从意思上容易看出来,是在for each迭代同时执行删除操作时发生的。即枚举操作和删除操作同步执行时候会抛出同步异常。

   注:for each的实现其实是使用Iterator进行迭代的,即元素枚举。

 

4.解决方案

      个人想到一个个人认为较好的解决方案,其执行的时间复杂度为o(n),空间复杂度为o(1),主要就是用index i,j,遍历一般将待删除的元素放到List的最后;然后对List取subList(0,i+1).注意这里自己没有实用remove方法,因为看了List remove操作的代码你就会明白,每删除一个操作,需要调用System.arraycopy将后面的元素拷贝上前,直观看,个人认为这个性能不是很好,尤其该代码不是仅删除一个元素,而是针对元素值进行删除的,当然啦,据说System.arraycopy性能蛮高,还没看,有时间看看研究一下。。

代码如下:

if(null != objList && !objList.isEmpty()){
    int i=0, len = objList.size();
    for (; i<len; i++) {
        if (objList.get(i).getCode().equals("gewala")) {
            objList.set(i--, objList.get(len-1));
            objList.set(--len, null);
        }
    }
    objList = objList.subList(0, len);
}

注:subList操作并不会为数组开辟新的空间,因此空间复杂度不会是O(n),另外这也使得我们不能随意的对subList做修改,否则对原始List也进行的相同操作,如果想修改最后new开辟新的空间。

陷阱bug:使用上面代码是存在一个风险的,就是在对objList的后面元素设置为null时,会导致元素的个数与List的size不一致的问题,所以该方法在缓存重复使用时可能会造成陷阱奥。。O(∩_∩)O~,解决办法很简单,修改null那条语句就可以,这里不再赘述啦。。。

 

posted @ 2014-05-23 15:21  fsailuo  阅读(143)  评论(0编辑  收藏  举报