3 回答

TA貢獻1993條經驗 獲得超6個贊
javadoc中對此進行了解釋ArrayList
,您正在使用以下命令remove()
修改列表:set()
Iterator
此類的
iterator
和listIterator
方法返回的迭代器是快速失敗的:如果在創建迭代器后的任何時間對列表進行結構修改,除了通過迭代器自己的刪除或添加方法之外的任何方式,迭代器將拋出ConcurrentModificationException
.?因此,面對并發修改,迭代器會快速而干凈地失敗,而不是在未來不確定的時間冒任意、非確定性行為的風險。

TA貢獻1812條經驗 獲得超5個贊
當顯示的代碼顯然不是產生異常的代碼時,很難對問題進行診斷,因為它甚至無法編譯。remove的方法不Iterator接受參數,并且該set方法是在 上定義的,但您的代碼僅ListIterator將變量聲明為。iIterator
固定版本
private void myMethod(ArrayList<Integer> input) {
ListIterator<Integer> i = input.listIterator();
while (i.hasNext()) {
Integer in = i.next();
if (in < 10)
i.remove();
else
i.set(in*in);
}
}
會毫無問題地運行。您的一般問題的答案是,每次修改都會使所有現有迭代器無效,除了當您確實使用迭代器而不是直接使用集合接口進行修改時用于進行修改的迭代器。
但在您的代碼中,只有一個迭代器,它僅針對這一操作而創建和使用。只要不重復使用同一個集合的迭代器,就不會出現失效問題。無論如何,先前操作中存在的迭代器都會被放棄,并且后續操作中使用的迭代器還不存在。
盡管如此,它還是更容易使用
private void myMethod(ArrayList<Integer> input) {
input.removeIf(in -> in < 10);
input.replaceAll(in -> in*in);
}
反而。與原始代碼不同,這會執行兩次迭代,但正如本答案中所解釋的,removeIf在性能確實很重要的情況下,實際上會比基于迭代器的刪除更快。
但問題仍然存在。顯示的代碼不會導致ConcurrentModificationException,因此您的實際問題在其他地方,并且可能仍然存在,無論如何實現這一方法。

TA貢獻1815條經驗 獲得超10個贊
我對 Java ListIterators 的了解不夠,無法回答這個問題,但看來我在這里遇到了 XY 問題。使用 Java Streams 似乎可以更好地解決這個問題,即通過對原始 ArrayList 中的每個元素執行函數來刪除元素或將元素映射到新的 ArrayList 中。
private ArrayList<Integer> myMethod(ArrayList<Integer> input) {
ArrayList<Integer> results = input.stream().filter(
in -> (in < 10)).collect(Collectors.toCollection(ArrayList::new));
results = input.stream().map(
in -> in*in).collect(Collectors.toCollection(ArrayList::new));
return results;
}
添加回答
舉報