3

このコードの実行中に ConcurrentModificationException を取得しています。なぜそれが起こっているのか理解できませんか?

private void verifyBookingIfAvailable(ArrayList<Integer> list, int id) {

        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
                int value = iterator.next();
                if (value == id) {
                    int index = list.indexOf(id);

                    if (index != -1) {
                        list.remove(index);
                    }
                }
        }
    }

前もって感謝します。

4

4 に答える 4

11

listをスローできる参照自体を使用して、リスト内の要素を削除していますConcurrentModificationException。これは常に機能するわけではありませんが、完全に機能することは保証されていません。

また、 を使用Iteratorしてリストを反復処理しても、 を使用しないlist.removeでください。要素を削除するためにのみ使用する必要がありますiterator.remove()。そうしないと、イテレータを使用するか拡張 for ループを使用するかに関係なく、違いはありません。

したがって、iterator.remove()要素を削除するために使用します。

if (index != -1) {
    iterator.remove(value);
}

詳細については、この投稿を参照してください: - java-effective-equivalent-to-removing-while-iterating-a-collection

于 2012-11-09T11:44:39.697 に答える
1

ArrayList単純に、反復処理中に要素を削除しようとしているからです。この問題を解決するには、java.util.concurrent.CopyOnWriteArrayListを使用してください。お役に立てれば。

于 2012-11-09T11:45:32.963 に答える
0

何が起こるかというと、ArrayList イテレーターは、反復中に変更できるように設計されていないということです。

したがって、一貫性のないデータから発生するより深刻なバグを回避するために、アイテムを削除すると更新され、反復するときにチェックされる変更カウントがあります。

ArrayList.java から:

411     public E remove(int index) {
412         rangeCheck(index);
413 
414         modCount++;
415         E oldValue = elementData(index);
416 
417         int numMoved = size - index - 1;
418         if (numMoved > 0)
419             System.arraycopy(elementData, index+1, elementData, index,
420                              numMoved);
421         elementData[--size] = null; // Let gc do its work
422 
423         return oldValue;
424     }
     ...
779 
780         final void checkForComodification() {
781             if (modCount != expectedModCount)
782                 throw new ConcurrentModificationException();
783         }

javadoc で指定されているとおり:

返されるリスト反復子はフェイルファストです。

この問題を回避するには、リストを直接削除するのではなく、反復子を使用して現在の要素を削除します。イテレータのremoveメソッドにより、イテレータの一貫性が保たれます。

于 2012-11-09T11:45:36.090 に答える
0

これを試して

private void verifyBookingIfAvailable(ArrayList<Integer> list, int id) {

        List<Integer> tempList =new ArrayList<Integer>();
    tempList.addAll(list);

     for(Integer value :tempList) {

         if (value == 1) {
             int index = tempList.indexOf(1);

             if (index != -1) {

                 list.remove(index);
             }
         }
 }
}

反復中にオブジェクトを削除しています

于 2012-11-09T11:45:37.113 に答える