java修改集合抛出ConcurrentModificationException异常

测试代码为:
html

public static void main(String[] args) {
		List<String> strList = new ArrayList<String>();
		strList.add("1");
		strList.add("2");
		strList.add("3");
		strList.add("4");
		for(String str:strList){
			if(str.equals("4")){
				strList.remove(str);
			}
		}
	}

运行后结果以下:
java

跟踪代码,抛出异常的地方具体在:函数

public E next() {
            checkForComodification();
	    try {
		E next = get(cursor);
		lastRet = cursor++;
		return next;
	    } catch (IndexOutOfBoundsException e) {
		checkForComodification();
		throw new NoSuchElementException();
	    }
	}

遍历时返回一个元素以前,会调用checkForComodification()函数进行检查,该函数实现为:测试

final void checkForComodification() {
	    if (modCount != expectedModCount)
		throw new ConcurrentModificationException();
	}

    modCount 为ArrayList修改的次数,expectedModCount 为指望修改的次数,在删除第四个元素以前,modCount 和expectedModCount 均为4(4次add),而调用ArrayList的remove()方法后,modCount 变为5,但该方法未修改expectedModCount ,其值仍为4,所以出现上述异常。spa

    解决方法为:单线程环境中,使用 Iterator的remove()方法取代ArrayList的remove()方法,能够避免ConcurrentModificationException异常。线程

    巧合的是,若是要删除的元素正好是集合中倒数第二个元素,则不会抛出此异常。Iterator遍历获取一个元素以前会先调用hasNext()方法来判断是否还有元素,该方法实现为:code

public boolean hasNext() {
            return cursor != size();
	}

其中cursor为遍历的位置,从0开始,在上面的next()方法中被更新。htm

    删除倒数第二个元素"3"后,已经访问了3个元素,cursor指向下一个应该访问的元素位置,即3,而size()也返回3,hasNext()返回false,就不会调用next()方法,所以也不存在ConcurrentModificationException异常blog

    删除元素"4"后,cursor的值变为4,而size()返回3,hasNext()返回true,所以调用next()方法时就会抛出ConcurrentModificationException异常rem



附上一篇资料:

Java ConcurrentModificationException异常缘由和解决方法:

http://www.cnblogs.com/dolphin0520/p/3933551.html

相关文章
相关标签/搜索