我正在尝试通过循环遍历列表(嵌套循环)进行迭代。请考虑以下代码:
ArrayList<Integer> list = new ArrayList<Integer>(); // 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中实现同样的东西而不会抛出异常的循环?
答案 0 :(得分:5)
当你迭代它时导致异常,显然会修改list
。
您可以使用另一个列表来维护要删除的元素列表,并在最后删除它们。
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
ArrayList<Integer> del = new ArrayList<Integer>(); // 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);
答案 1 :(得分:2)
使外部迭代遍历列表的副本。
for (int i : new ArrayList<>(list)) {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
int n = iterator.next();
if (n % i == 0) {
iterator.remove();
}
}
}
答案 2 :(得分:1)
您收到ConcurrentModificationException
因为,在执行for
循环时,您正在尝试修改list
。
我不确定以下是否是优雅的解决方案,但下面的内容可能有效:
Iterator<Integer> iterator = list.iterator();
int i=1;
while (iterator.hasNext()) {
int n = iterator.next();
if (n % i == 0) {
iterator.remove();
}
i++;
}
答案 3 :(得分:0)
您无法从正在迭代的列表中删除项目。一种选择是将您需要的项目添加到另一个列表中。最后,您列出了您需要的项目。或者您可以迭代原始列表的克隆。
答案 4 :(得分:0)
out:for(int h=0; h<tempAl.size(); h++) {
if(tempAl.get(0).split("\\s")[0].equals("OFF")){
tempAl.remove(0);
h=-1;
continue;
}
if(tempAl.get(h).split("\\s")[0].equals("ON")){
ONTime= tempAl.get(h);
///rest fof the code
}
我认为您也可以在从arraylist中删除元素后更改索引。
答案 5 :(得分:0)
我没试过,但要么使用:
List<Integer> list = new ArrayList<Integer>();
// add some values to it
for(Iterator<Integer> iterator1 = list.iterator(); iterator1.hasNext();) {
int i = iterator1.next();
for(Iterator<Integer> iterator2 = list.iterator(); iterator2.hasNext();){
int n = iterator.next();
if(n % i == 0) {
iterator2.remove();
}
}
}
或者如果仍然抛出ConcurrentModificationException(我不确定如果使用由同一列表支持的2个迭代器会发生什么),那么使用:
List<Integer> list = new ArrayList<Integer>();
// add some values to it
for(int i : new ArrayList(list)){ // copy list
...
}
答案 6 :(得分:0)
foreach
java语法隐藏了一个迭代器但是隐藏它,就不可能在这个上调用remove
方法。
所以我会这样做:
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
int count = 0;
for(Iterator<Integer> it = list.iterator();it.hasNext();count++){ //increments count++
Integer currentInt = it.next();
if(currentInt % count == 0){
it.remove();
}
}
您可以看到,无需辅助迭代器即可实现相同的功能。
您无法在同一时间内遍历同一列表。
总而言之,每当列表被平行更改或迭代时,modcount
变量用于检测自身的意外更改。
因此导致ConcurrentModificationException
。
它经常出现在多线程环境中,开发人员必须意识到这一点。
此外,更喜欢使用for
循环而不是while
循环来迭代集合。
为什么?
因为使用while
方式,在循环之后让迭代器对象仍然在范围内,而使用for
时,它不会。对it.next()
的简单尴尬调用最终会导致NoSuchElementException
。
保持最佳做法;)