簡體   English   中英

在同一arraylist上使用addall和removeall的並發修改異常

[英]concurrent modification exception on using addall and removeall on same arraylist

我必須從ArrayList刪除一個子列表,並在開始時添加相同的子列表。 我正在使用以下代碼-

for(int i =0 ;i <m ; i++){
    List<Integer> t = q.subList(j, k);
    q.removeAll(t);
    q.addAll(0, t);
}

我正在對addAll並發異常修改。 我嘗試從q創建一個副本列表,然后在其上調用addAll ,但仍然在同一行上引發錯誤。

for(int i =0 ;i <m ; i++){
    List<Integer> t = q.subList(j, k);
    q.removeAll(t);
    ArrayList<Integer> q1= new ArrayList<Integer>(q);
    q1.addAll(0, t);
}

如何在同一數據列表上執行這兩項操作?

subList的Javadoc指出:

如果后備列表(即此列表)以結構方式(而不是通過返回的列表)進行了修改,則此方法返回的列表的語義將變得不確定。 (結構修改是指更改此列表的大小的結構修改,或者以其他方式干擾此列表的方式,即正在進行的迭代可能會產生錯誤的結果。)

這意味着調用removeAll可能會使subList返回的列表無效。

另外, addAll的Javadoc指出:

如果在操作進行過程中修改了指定的集合,則此操作的行為是不確定的。 請注意,如果指定的集合是此列表,並且是非空的,則會發生這種情況 。)

在您的情況下,您傳遞給addAllCollection是子列表,該子列表由要在其上調用addAll的原始List提供addAll

您可以做的是將子列表的元素存儲在單獨的ListcopyOfSubList )中,使用clear()刪除子列表的元素(這也會從原始List刪除它們),然后添加元素將copyOfSubList返回到原始List

for(int i =0 ;i < m ; i++) {
    List<Integer> t = q.subList(j, k);
    List<Integer> copyOfSubList = new ArrayList<> (t);
    t.clear ();
    q.addAll(0, copyOfSubList);    
}

您可以使用CopyOnWriteArrayList而不是ArrayList CopyOnWriteArrayList迭代器從不會拋出ConcurrentModificationException 創建迭代器后,它將保留列表內容的副本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM