2013-06-06 9 views
17

単純なループでコレクションのループを取り除こうとしているのであれば、私はこの例外が発生するでしょう:java.util.ConcurrentModificationException。しかし、私はIteratorを使用していますが、それでも私はこの例外を生成します。任意のアイデアなぜ、どのようにそれを解決するには?イテレータを使ったjava.util.ConcurrentModificationException

HashSet<TableRecord> tableRecords = new HashSet<>(); 

... 

    for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext();) { 
     TableRecord record = iterator.next(); 
     if (record.getDependency() == null) { 
      for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext();) { 
       TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception 
       if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) { 
        iterator.remove(); 
       } 
      } 
     } 
    } 

答えて

27

あなたは、あなたがイテレータからremoveメソッドを使用する場合にのみ反復れているリストの項目を削除することができます代わりにtableRecords.remove()

iterator.remove()を使用する必要があります。

EDIT:あなたはイテレータを作成すると

、それがコレクションに適用された変更のカウントを開始します。イテレータは、そのメソッドを使用せずに(または同じコレクションの別のイテレータを使用して)何らかの変更が行われたことを検出した場合、同じ要素に対して2回以上スキップしたりスキップしたりすることを保証することはできないため、この例外がスローされます。

それはあなたが唯一のiterator.remove(そして唯一のイテレータを持つ)を経由して項目を削除するようにコードを変更する必要があることを意味

OR

削除する項目のリストを作るあなたは反復終了後に、それらを削除。

+0

それはおそらく問題は解決されませんように、2つのネストされたイテレータがあります。 – assylias

+2

まだ同じです。 – user2219247

+0

@assyliasそれは本当です、私は2番目を見ませんでした。この例外に関する説明を追加しました。 –

0

HashSetのイテレーターの契約では、そのspcificイテレーターのremoveメソッド以外の方法でハッシュセットから削除することはできません。 dependencyItの観点から、removeメソッドを呼び出す以外のアイテムを削除したので、ConcurrentModificationExceptionがスローされます。

同じレコードIDを持つハッシュセットからレコードを削除したいようです。あなたのレコードのequalshashcodeメソッドをオーバーライドして、同じidのレコードが等しく、同じハッシュコードを持つようにするのは簡単ではないでしょうか? (それが当然意味を持っている場合)

0

問題は、同時に2つのイテレータがスコープ内にあり、互いに「戦っている」ということです。

for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext();) { 
    TableRecord record = iterator.next(); 
    if (record.getDependency() == null) { 
     for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext();) { 
      TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception 
      if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) { 
       iterator.remove(); 
       break; // ADD THIS LINE 
      } 
     } 
    } 
} 

JavaのIterator sはその基礎となるコンテナを使用して変更されずに変更されるたびに「速い失敗」することを意図している。問題を解決する最も簡単な方法は、あなたが一致するものを見つけた場合、内側のループの外に救済するだけですIterator。ネストされたイテレータを使用しているため、remove()の操作は1つに発行され、それが引き続き使用される場合はExceptionがスローされます。このため、remove()を発行する必要がある場合は、「外部」イテレータ(これを実行中)でそれを実行し、後で2番目のイテレータの使用を中止する必要があります(break文が追加します)。我々は 次の要素を取得しようとする基になるコレクション毎回の 構造における任意の修正のための

1

イテレータフェイルファストプロパティをチェックします。変更が見つかった場合は、 ConcurrentModificationExceptionがスローされます。 CollectionクラスのIterator のすべての実装は、ConcurrentHashMapおよびCopyOnWriteArrayListのような同時の コレクションクラスを除き、設計上フェイルファーストです。

出典:Googleの

あなたがより良い以下の書かれた例を理解します: -

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Iterator; 
import java.util.List; 

public class IteratorExp { 
    public static void main(String... q) { 
     //CASE - ONE 
     List<String> strList = new ArrayList<>(Arrays.asList("a", "b", "c")); 
     Iterator<String> itr = strList.iterator(); 
     /* 
     * strList.add("e"); strList.add("f"); strList.add("g"); 
     */ 
     while (itr.hasNext()) { 
      System.out.println(itr.next()); 
     } 
     /* 
     * Exception in thread "main" java.util.ConcurrentModificationException 
     * at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at 
     * java.util.ArrayList$Itr.next(Unknown Source) at 
     * IteratorExp.main(IteratorExp.java:14) 
     */ 

     //CASE - TWO 
     List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)); 
     Iterator<Integer> itrOne = intList.iterator(); 
     Iterator<Integer> itrTwo = intList.iterator(); 
     for (; itrOne.hasNext();) { 
      if (itrOne.next().equals(5)) { 
       itrOne.remove(); // #1 
       //intList.remove(itrOne.next()); // #2 
      } 
     } 
     for (; itrTwo.hasNext();) { 
      if (itrTwo.next().equals(5)) { 
       itrTwo.remove(); // #1 
       //intList.remove(itrTwo.next()); // #2 
      } 
     } 

     /* 
     * Exception in thread "main" java.util.ConcurrentModificationException 
     * at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at 
     * java.util.ArrayList$Itr.next(Unknown Source) at 
     * IteratorExp.main(IteratorExp.java:35) 
     */ 
    } 
} 
関連する問題