簡體   English   中英

從 ArrayList 同時刪除兩個對象而不導致 ConcurrentModificationException?

[英]Remove two objects at the same time from an ArrayList without causing a ConcurrentModificationException?

我有以下代碼拋出 ConcurrentModificationException。 有人可以解釋為什么會這樣嗎?

public void foo(ArrayList<Bet> bets)
   Iterator it1 = bets.iterator();
   while(it1.hasNext())
      Bet b1 = (Bet) bets.next()
      Iterator it2 = bets.iterator();
      while(it2.hasNext())
         if(bet1.equals(bet2))
             it2.remove();
             it1.remove();   //ConcurrentModificationException thrown here

對於每個 iterator.next() 調用,我只能調用 iterator.remove() 一次,並且在下一次調用 iterator.next() 之前調用 remove 兩次會導致這種情況嗎?

任何幫助都會非常感謝。

您需要將所有刪除收集到一個Set ,並在所有迭代完成后將其刪除。

public void foo(ArrayList<Bet> bets) {
    Set<Bet> remove = new HashSet<Bet>();
    for ( Bet bet1 : bets ) {
        for ( Bet bet2 : bets ) {
            // Not the same but equal.
            if ( bet1 != bet2 && bet1.equals(bet2)) {
                remove.add(bet1);
                remove.add(bet2);
            }
        }
    }
    bets.removeAll(remove);
}

對於每個 iterator.next() 調用,我只能調用 iterator.remove() 一次,並且在下一次調用 iterator.next() 之前調用 remove 兩次會導致這種情況嗎?

如果你在沒有next()情況next()調用remove() next()你會得到IllegalStateException

您收到ConcurrentModificationException是因為您在同一個 ArrayList 上使用了 2 個迭代器,並且它們都從列表中刪除了元素。

如果要從列表中刪除重復項,可以使用 @OldCurmudgeon 代碼或僅使用以下 2 行:

bets.clear();
bets.addAll(new LinkedHashSet(bets));

當使用 remove(int i)(即使用索引)或 remove(Object o) 從 Java 中的 ArrayList 中刪除元素時,必須在底層數組中填充因刪除元素而產生的間隙。 這是通過將任何后續元素向左移動(從它們的索引中減去一個)來完成的。 System.arrayCopy 方法用於此目的。 過程也可以稱為混洗。

System.arraycopy(elementData, index+1, elementData, index, numMoved);

這里 index+1 是源位置,index 是目標位置。 由於位置 index 處的元素被刪除,因此從 index+1 開始的元素被復制到從 index 開始的目的地。

您在循環中執行此操作,Arraylist 在給定時刻保持確定狀態變得困難,因此可能會丟失一些更改,為了避免這種情況,我們有 Concurrentmodification 異常。

暫無
暫無

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

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