2

注意:请在下面查看我的编辑:

一段时间以来,我一直在尝试编写一个洗牌模拟 java 程序。高级概述是这样的:

  • 做一个甲板
  • 切入myDeck我的handLefthandRight
  • 虽然我handRight的不是空的:
    • 从右手向左移动随机数量的牌。

这个移动部分是通过以下方法完成的:

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)循环不会在这里工作。我在这里看到了一种解决方案的尝试,但我不确定它是否能巧妙地解决我的问题。删除某些内容不会导致此问题,添加与 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函数创建一个由初始列表支持的列表,即所有操作都反映在子列表 -> 列表中,反之亦然。所以下面的代码是无效的:

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

与其使用 subList,不如使用循环将卡片一张一张地从 handRight 移动到 handLeft,如下所示:

    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 回答