2

注意:以下の私の編集を見てください:

しばらくの間、カード シャッフル シミュレーション Java プログラムを作成しようとしています。高レベルの概要は次のとおりです。

  • デッキを作る
  • myDeck私のhandLeftとにカットhandRight
  • myhandRightは空ではありませんが:
    • 乱数のカードを右手から左手に移動します。

この可動部は以下の方法で行います。

public ArrayList<Card> leftShuffle(int fudge){
    Random randomGenerator = new Random();
    int numberOfCardsToMove = 0;
    while(!handRight.isEmpty()){
        numberOfCardsToMove = randomGenerator.nextInt(fudge);
        if (numberOfCardsToMove<handRight.size()){
            List<Card> cardsBeingMoved = handRight.subList(0, numberOfCardsToMove);
            handRight.removeAll(cardsBeingMoved);  <---line 81
            handLeft.addAll(cardsBeingMoved);      <---line 82
        }else{
            handLeft.addAll(handRight);
            handRight.clear();
        }
    }
    return handLeft;
}

ただし、SubList cardsBeingMovedJava にカードを追加しようとすると、異常が発生し、次の例外が発生します。

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1091)
at java.util.ArrayList$SubList.size(ArrayList.java:921)
at java.util.AbstractCollection.toArray(AbstractCollection.java:136)
at java.util.ArrayList.addAll(ArrayList.java:497)
at org.Craig.CardShuffling.Scientist.leftShuffle(Scientist.java:82)
at org.Craig.CardShuffling.Scientist.shuffle(Scientist.java:49)
at org.Craig.CardShuffling.Launcher.main(Launcher.java:11)

while(it.hasNext)今ではイテレータとその仕組みに精通していますが、標準的なループはここでは機能しないと思います。ここで解決策の試みを 1 回見たことがありますが、それが私の問題にきちんと対応しているかどうかはわかりません。何かを削除してもこの問題は発生せず、while 句に関係のない何かを追加すると問題が発生します。それ以外の場合は、条件を次のように変更してwhile(handLeft.size!=52)から、最後に削除することができますhandRight

CopyOnWriteArrayList クラスを使用してみましたが、同じ方法でエラーが発生しました (付録 A を参照)。同じリストが同時に変更されないように、さまざまな「保持」リストを疲れさせましたが、それでも例外が発生します。 .

この問題を解決するにはどうすればよいですか? 私がまだ考えていないイテレータを使用する賢い方法はありますか?


付録 A

シャッフル法

    public ArrayList<Card> shuffle (int fudge, Shuffling method){
    cutDeck(fudge);
    switch(method){
    case right:
        myDeck.setDeck(rightShuffle(fudge));
        break;
    case left:
        myDeck.setDeck(leftShuffle(fudge));
        break;
    case both:
        myDeck.setDeck(bothShuffle(fudge));
        break;
    }
    return myDeck.getDeck();
}

CopyOnWriteArrayList 例外スタック トレース。

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(CopyOnWriteArrayList.java:1130)
at java.util.concurrent.CopyOnWriteArrayList$COWSubList.size(CopyOnWriteArrayList.java:1170)
at java.util.AbstractCollection.toArray(AbstractCollection.java:136)
at java.util.concurrent.CopyOnWriteArrayList.addAll(CopyOnWriteArrayList.java:770)
at org.Craig.CardShuffling.Scientist.leftShuffle(Scientist.java:82)
at org.Craig.CardShuffling.Scientist.shuffle(Scientist.java:49)
at org.Craig.CardShuffling.Launcher.main(Launcher.java:11)

付録 B:

メソッドを次のように変更しました。

    public ArrayList<Card> leftShuffle(int fudge){
    Random randomGenerator = new Random();
    int numberOfCardsToMove = 0;
    while(!handRight.isEmpty()){
        numberOfCardsToMove = randomGenerator.nextInt(fudge);
        if (numberOfCardsToMove<handRight.size()){
            List<Card> cardsBeingMoved = handRight.subList(0, numberOfCardsToMove);
            handRight.removeAll(cardsBeingMoved);
            /* cardBeingMoved is just a view, 
             * clearing it removes the same cards from handRight*/
            cardsBeingMoved.clear();
        }else{
            handLeft.addAll(handRight);
            handRight.clear();
        }
        System.out.println("Size of Deck one:" + handRight.size() + "\n");
        System.out.println("Size of Deck one:" + handLeft.size() + "\n");
    }
    return handLeft;
}

例外はこれです。

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1091)
at java.util.ArrayList$SubList.size(ArrayList.java:921)
at java.util.AbstractList.clear(AbstractList.java:234)
at org.Craig.CardShuffling.Scientist.leftShuffle(Scientist.java:86)
at org.Craig.CardShuffling.Scientist.shuffle(Scientist.java:49)
at org.Craig.CardShuffling.Launcher.main(Launcher.java:11)
4

3 に答える 3

2

サブリストはビューであり、コピーではありません。したがって、要素を削除してcardsBeingMovedいると同時に、それを他の何かに使用しようとしています。

代わりに、次の操作を行います。

 handLeft.addAll(cardsBeingMoved);
 cardsBeingMoved.clear();
于 2013-02-16T21:49:40.173 に答える
1

subList を使用する代わりに、次のように loop を使用してカードを handRight から handLeft に 1 つずつ移動してはどうでしょうか。

    public ArrayList<Card> leftShuffle(int fudge){
    Random randomGenerator = new Random();
    int numberOfCardsToMove = 0;
    while(!handRight.isEmpty()){
        numberOfCardsToMove = randomGenerator.nextInt(fudge);
        if (numberOfCardsToMove<handRight.size()){
            for(int i = 0; i < numberOfCardsToMove; i++){
                handLeft.add(handRight.get(i));
                handRight.remove(i);
            }
        }else{
            handLeft.addAll(handRight);
            handRight.clear();
        }
    }
    return handLeft;
}
于 2013-02-16T22:48:09.943 に答える
1

このsubList関数は、最初のリストに裏打ちされたリストを作成します。つまり、すべての操作はサブリスト -> リストから反映され、その逆も同様です。したがって、以下のコードは無効です。

List<Card> cardsBeingMoved = handRight.subList(0, numberOfCardsToMove);
handRight.removeAll(cardsBeingMoved);  <---line 81
handLeft.addAll(cardsBeingMoved);      <---line 82
于 2013-02-16T21:49:47.797 に答える