1

私は実際にコレクションと例外を学んでいますが、なぜこれが機能するのか理解できません:

List<Integer> intList = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
for (Integer s : intList) {
     Collections.shuffle(intList);
     System.out.println(s);
 }

ドキュメントを読むと、それは述べています

この例外は、そのような変更が許可されていない場合に、オブジェクトの同時変更を検出したメソッドによってスローされる場合があります。

Collections のソースコードを見ると:

public static void shuffle(List<?> list) {
        if (r == null) {
            r = new Random();
        }
        shuffle(list, r);
}

だから私はシャッフル機能を見てみましょう:

public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));

            // Dump array back into list
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

最後に swap 関数を呼び出します:

public static void swap(List<?> list, int i, int j) {
        final List l = list;
        l.set(i, l.set(j, l.get(i)));
}

これは、反復中に現在のリストを変更しませんか (または、これはこの行が原因ですfinal List l = list;) ? 私は何か重要なものを見逃していると思います。

4

2 に答える 2

6

答えはドキュメントにあります-私の強調:

(構造変更とは、1 つまたは複数の要素を追加または削除する操作、またはバッキング配列のサイズを明示的に変更する操作です。要素の値を設定するだけでは、構造変更ではありません。 )

...

このクラスの iterator および listIterator メソッドによって返される反復子は、フェイルファストです。反復子の作成後に、反復子自体の remove メソッドまたは add メソッド以外の方法でリストが構造的に変更された場合、反復子は ConcurrentModificationException をスローします。したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗します。

shuffleのみを呼び出すsetため、構造的な変更を実行していないため、反復子は例外をスローしません。

于 2013-10-22T18:19:46.087 に答える
3
 for (int i=size; i>1; i--)
   swap(list, i-1, rnd.nextInt(i));

それ自体は、ここで繰り返されるわけではありません。関係ありませんIterator。そして 2 番目のブランチでは、ConcurrentModificationException を回避するために行うべき方法である を介してすべての変更をIterator行います。

于 2013-10-22T18:19:48.703 に答える