gpt4 book ai didi

java - 使用 foreach 循环时没有 ConcurrentModificationException

转载 作者:行者123 更新时间:2023-12-01 19:31:59 25 4
gpt4 key购买 nike

我正在尝试运行以下代码:

List<String> l = new ArrayList<String>();
l.add("jim");
l.add("pam");

for(String s : l) {
l.remove(s);
}

但我没有得到任何异常(exception)。 foreach循环不是使用了Iterator,我们在迭代时不能改变List的结构吗?

编辑:

当列表有 3 个以上元素时,我收到 ConcurrentModificationException。为什么会出现这种情况?

最佳答案

您没有收到 ConcurrentModificationException 的原因是您的列表只有两个元素,这会阻止实现检测并发修改。以下是 ArrayList 使用的 Java 13 Iterator 实现:

private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;

// prevent creating a synthetic constructor
Itr() {}

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

@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}

public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int size = ArrayList.this.size;
int i = cursor;
if (i < size) {
final Object[] es = elementData;
if (i >= es.length)
throw new ConcurrentModificationException();
for (; i < size && modCount == expectedModCount; i++)
action.accept(elementAt(es, i));
// update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}

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

如您所见,它检查 next() 方法中的并发修改,但不检查 hasNext() 方法中的并发修改。这个很重要。如果您不知道,增强型 for 循环会在幕后使用 Iterator。换句话说,您的 for-each 循环相当于:

for (Iterator<String> itr = l.itr(); itr.hasNext(); ) {
String e = itr.next();
l.remove(e);
}

一旦循环删除第一个元素,列表中就只剩下一个元素。但是,该元素已向下移动索引 (1 → 0),但迭代器的光标已增加 1。这使得光标等于大小,因此循环不会执行第二次。由于循环不会再次执行,因此不会再次调用 next() 方法,并且不会检查并发修改。这也会产生将第二个元素保留在列表中的副作用。

一旦列表包含三个或更多元素,循环就会执行第二次,从而允许它检测并发修改。

关于java - 使用 foreach 循环时没有 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59479499/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com