Bhe*_*ung 173 java foreach list concurrentmodification
注意:我知道这个Iterator#remove()方法.
在下面的代码示例中,我不明白为什么List.removein main方法抛出ConcurrentModificationException,而不是在remove方法中.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
pus*_*shy 258
原因如下:正如在Javadoc中所说:
此类的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出ConcurrentModificationException.
这个检查是在next()迭代器的方法中完成的(你可以通过stacktrace看到).但是我们next()只有在hasNext()传递真实时才会到达该方法,这是由每个人调用以检查是否满足边界.在你的remove方法中,当hasNext()检查它是否需要返回另一个元素时,它会看到它返回了两个元素,现在在删除一个元素之后,列表只包含两个元素.所有都是桃子,我们完成了迭代.不会发生对并发修改的检查,因为这是在next()从未调用过的方法中完成的.
接下来我们进入第二个循环.删除第二个数字后,hasNext方法将再次检查是否可以返回更多值.它已经返回了两个值,但列表现在只包含一个.但这里的代码是:
public boolean hasNext() {
return cursor != size();
}
Run Code Online (Sandbox Code Playgroud)
1!= 2,所以我们继续这个next()方法,现在意识到某人一直搞乱列表并触发异常.
希望能够解决你的问题.
List.remove()ConcurrentModificationException从列表中删除第二个最后一个元素时不会抛出.
Jam*_*sev 42
处理它的一种方法是从一个Collection(不是Collection本身)的副本中删除一些东西,如果适用的话.Clone它的原始集合通过一个副本来制作Constructor.
当不允许这样的修改时,检测到对象的并发修改的方法可能抛出此异常.
对于您的具体情况,首先,我不认为final是一种方法去考虑您打算修改过去的声明列表
private static final List<Integer> integerList;
Run Code Online (Sandbox Code Playgroud)
还可以考虑修改副本而不是原始列表.
List<Integer> copy = new ArrayList<Integer>(integerList);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
copy.remove(integer);
}
}
Run Code Online (Sandbox Code Playgroud)
Rig*_*key 13
删除项目时,forward/iterator方法不起作用.您可以删除元素而不会出错,但是当您尝试访问已删除的项目时,您将收到运行时错误.你不能使用迭代器,因为当pushy显示它会导致ConcurrentModificationException,所以改为使用常规的for循环,但是后退一步.
List<Integer> integerList;
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
int size= integerList.size();
//Item to remove
Integer remove = Integer.valueOf(3);
Run Code Online (Sandbox Code Playgroud)
一个办法:
如果要删除列表元素,则以相反的顺序遍历数组.只需在列表中向后移动即可避免访问已删除的项目,从而删除了例外.
//To remove items from the list, start from the end and go backwards through the arrayList
//This way if we remove one from the beginning as we go through, then we will avoid getting a runtime error
//for java.lang.IndexOutOfBoundsException or java.util.ConcurrentModificationException as when we used the iterator
for (int i=size-1; i> -1; i--) {
if (integerList.get(i).equals(remove) ) {
integerList.remove(i);
}
}
Run Code Online (Sandbox Code Playgroud)
此代码段将始终抛出ConcurrentModificationException.
规则是"你不能修改(在列表中添加或删除元素),同时使用迭代器迭代它(当你使用for-each循环时会发生这种情况)".
JavaDoc中:
此类的iterator和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出ConcurrentModificationException.
因此,如果您想要修改列表(或一般的任何集合),请使用迭代器,因为它知道修改,因此将正确处理.
希望这可以帮助.
我遇到了同样的问题,但是如果我将en元素添加到迭代列表中.我是这样做的
public static void remove(Integer remove) {
for(int i=0; i<integerList.size(); i++) {
//here is maybe fine to deal with integerList.get(i)==null
if(integerList.get(i).equals(remove)) {
integerList.remove(i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在一切都很顺利,因为你没有在列表上创建任何迭代器,你"手动"迭代它.并且条件i < integerList.size()永远不会欺骗你,因为当你删除/添加List列表减少/增量的List大小时.
希望它有所帮助,对我来说这是解决方案.