NB: Please see my edit below:
I've been trying to write a card shuffling simulation java program for a while now. The high level overview is this:
- Make a deck
- Cut
myDeck
into myhandLeft
andhandRight
- While my
handRight
is not empty:- Move a random number of cards from the right hand to the left.
This moving part is done by the method below:
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;
}
However, when I try to add cards to the SubList cardsBeingMoved
java freaks out and gives me this exception:
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)
Now I'm familiar with iterators and how they work, but I don't think the standard while(it.hasNext)
loop will work here. I've seen one attempt at a solution here but I'm not sure if it maps neatly on to my problem. Removing something is not causing this issue, adding something unrelated to the while clause is causing the issue. Otherwise I could change the condition to something like while(handLeft.size!=52)
and then remove from handRight
at the end.
I've tried using the CopyOnWriteArrayList class, but that errors the same way (see appendix A), I've tired various 'holding' lists so that the same list isn't being altered at the same time but it still give the exception.
How do I get past this issue? Is there a clever way to use iterators I've not thought of yet?
Appendix A
Shuffle Method
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 stack trace.
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)
Appendix B:
I've changes the method to this:
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;
}
Now the exception is this.
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)