嵌套迭代遍历列表,然后是最终删除
我试图通过循环遍历列表(嵌套循环)迭代。 考虑以下代码:
ArrayList list = new ArrayList(); // add some values to it for(int i : list) { // ConcurrentModificationException Iterator iterator = list.iterator(); while(iterator.hasNext()) { int n = iterator.next(); if(n % i == 0) { iterator.remove(); } } }
上面的示例导致ConcurrentModificationException。 当然,移除元素的条件只是一个例子。
我确定我只是遗漏了一些东西; 但是我应该如何构建一个在Java 中实现相同function而不会抛出exception的循环 ?
当你迭代它导致execption时,显然修改了list
。 您可以使用另一个列表来维护要删除的元素列表,并在最后删除它们。
ArrayList list = new ArrayList (); // add some values to it ArrayList del = new ArrayList (); // Elements to be deleted for(int i : list) { // ConcurrentModificationException Iterator iterator = list.iterator(); while(iterator.hasNext()) { int n = iterator.next(); if(n % i == 0) { del.add(n); } } } list.removeALL(del);
使外部迭代迭代列表的副本。
for (int i : new ArrayList<>(list)) { Iterator iterator = list.iterator(); while (iterator.hasNext()) { int n = iterator.next(); if (n % i == 0) { iterator.remove(); } } }
您正在获取ConcurrentModificationException
因为在执行for
循环时您正在尝试修改list
。
我不确定以下是否是优雅的解决方案,但下面的内容可能有效:
Iterator iterator = list.iterator(); int i=1; while (iterator.hasNext()) { int n = iterator.next(); if (n % i == 0) { iterator.remove(); } i++; }
您无法从正在迭代的列表中删除项目。 一种选择是将您需要的项目添加到另一个列表中。 最后,您列出了您需要的物品。 或者您可以迭代原始列表的克隆。
我做了一些与你非常相似的事情。 哈哈对这段代码说。
out:for(int h=0; h
我想你也可以在从arraylist中删除元素后更改索引。
我没试过,但要么使用:
List list = new ArrayList (); // add some values to it for(Iterator iterator1 = list.iterator(); iterator1.hasNext();) { int i = iterator1.next(); for(Iterator iterator2 = list.iterator(); iterator2.hasNext();){ int n = iterator.next(); if(n % i == 0) { iterator2.remove(); } } }
或者如果这仍然抛出ConcurrentModificationException(我不确定如果你使用由同一列表支持的2个迭代器会发生什么),那么使用:
List list = new ArrayList (); // add some values to it for(int i : new ArrayList(list)){ // copy list ... }
foreach
java语法隐藏了一个迭代器但是隐藏它,就不可能在这个上调用remove
方法。
所以我会这样做:
ArrayList list = new ArrayList (); // add some values to it int count = 0; for(Iterator it = list.iterator();it.hasNext();count++){ //increments count++ Integer currentInt = it.next(); if(currentInt % count == 0){ it.remove(); } }
您可以看到,无需二级迭代器即可实现相同的function。
您无法在同一时间迭代同一列表。 总而言之,每当列表被平行更改或迭代时, modcount
变量用于检测其自身的意外更改。 因此导致ConcurrentModificationException
。 它经常出现在multithreading环境中,开发人员必须意识到这一点。
此外,更喜欢使用循环而不是循环迭代集合。
为什么?
因为使用while
方式,在循环之后让迭代器对象仍然在范围内,而对于for
,它不会。 对it.next()
一个简单的ackward调用最终会出现NoSuchElementException
。
保持最好的做法;)