![](/img/trans.png)
[英]Why this code does not trigger ConcurrentModificationException?
[英]Why does this Java code trigger a ConcurrentModificationException?
在循環的第一行我得到了錯誤,但我不明白為什么。 從我讀到的內容來看,只有當我迭代一個集合並嘗試同時修改它時才會發生這種情況,但事實並非如此。
在代碼中, list
的類型是ArrayList<Product>
。
void mergeSort() {
mergeSort(0, list.size() - 1); //128
}
private void mergeSort(int p, int r) {
if (p < r) {
int q = (p + r) / 2;
mergeSort(p, q); //133
mergeSort(q + 1, r);
merge(p, q, r); //135
}
}
private void merge(int p, int q, int r) {
List<Product> left = list.subList(p, q);
left.add(Product.PLUS_INFINITE);
List<Product> right = list.subList(q + 1, r);
right.add(Product.PLUS_INFINITE);
int i = 0;
int j = 0;
for (int k = p; k <= r; ++p) {
Product x = left.get(i).compareTo(right.get(j)) <= 0 ? left.get(i++) : right.get(j++); //147
list.set(k, x);
}
}
這是堆棧跟蹤:
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1415)
at java.base/java.util.ArrayList$SubList.get(ArrayList.java:1150)
at ProductList$ProductSort.merge(MainClass.java:147)
at ProductList$ProductSort.mergeSort(MainClass.java:135)
at ProductList$ProductSort.mergeSort(MainClass.java:133)
at ProductList$ProductSort.mergeSort(MainClass.java:128)
at ProductList.sort(MainClass.java:95)
at MainClass.main(MainClass.java:187)
subList
不會創建與指定范圍內的原始列表具有相同元素的新列表。 相反,它創建了一個“視圖”( docs ):
返回此列表部分的視圖 [...]。 返回的列表由該列表支持,因此返回列表中的非結構性更改會反映在該列表中,反之亦然。
另請注意:
如果后備列表(即此列表)以除通過返回列表之外的任何方式進行結構修改,則此方法返回的列表的語義將變為未定義。
這正是您在merge
中所做的。 您正在創建子列表left
。 然后用add
在結構上修改left
。 到目前為止,一切都很好。 但是隨后您創建了另一個子列表並對其進行right
修改。 這使得“ left
的語義變得未定義”。 這會導致下一次調用get
拋出異常。
最小的可重現示例:
ArrayList<String> list = new ArrayList<>(List.of("1", "2", "3", "4"));
List<String> left = list.subList(0, 2);
List<String> right = list.subList(2, 4);
right.add("5");
left.get(0);
子列表在這方面有點像迭代器( 您只能通過迭代器remove
,如果您通過原始列表刪除,可能會拋出 CME )。
解決此問題的一種簡單方法是創建子列表的副本,以便它們不再是“視圖”,而是實際上是獨立的列表:
List<Product> left = new ArrayList<>(list.subList(p,q));
List<Product> right = new ArrayList<>(list.subList(q+1,r));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.