Search code examples
javaandroidjava.util.concurrentconcurrentmodification

Exception in thread "main" java.util.ConcurrentModificationException (Head first java book example)


I tried to run a example from Head first java book - second edition (page 152). Its a game puzzle. Which targets Dotcoms(string) in grid to sunk them. But when I tried to run this puzzle I got an Java.util.concurrentModificationException error. I only got this error when I tried to sunk last dotCom(String) in grid. Suppose I have three string in grid like as below given picture. So when I started to give inputs I am able to remove(hit) first two strings(as they add in arrayList) but When I try to remove last string(a string which added last in Arraylist), then got concurrentmodificationException error. Sample code and console log is given below.
So why I got this error and how to remove this error.

enter image description here

class DotComBust{

    private GameHelper helper = new GameHelper();
    private ArrayList<DotCom> dotComList = new ArrayList<DotCom>();
    private int numofguesses=0;

    private void setUpGame(){
        DotCom one = new DotCom();
        one.setNames("Pets.com");
        DotCom two = new DotCom();
        two.setNames("eToys.com");
        DotCom three = new DotCom();
        three.setNames("Go2.com");
        dotComList.add(one);
        dotComList.add(two);
        dotComList.add(three);

        System.out.println("your goal is sunk three dot coms");
        System.out.println("Pets.com, eToys.com, Go2.com");
        System.out.println("Try to sink them all in fewest number of guesses");

        for(DotCom dotComToSet : dotComList){
            ArrayList<String> newLocation = helper.placeDotCom(3);
            dotComToSet.setLocationCells(newLocation);
        }

    }

        private void startPlaying(){
            while(!dotComList.isEmpty()){
                String userGuess = helper.getUserInput("Enter a guess");
                checkUserGuess(userGuess);
            }

            finishGame();
        }

        private void checkUserGuess(String userGuess){
            numofguesses++;
            String result = "miss";
            for(DotCom dotComToTest : dotComList){
                result = dotComToTest.checkYourself(userGuess);

                if(result.equals("hit")){
                    break;
                }
                if(result.equals("kill")){
                    dotComList.remove(dotComToTest);
                }
            }
        System.out.println(result);
        }


        private void finishGame(){
            System.out.println("All the dotcoms are dead your stock is worthless");
            if(numofguesses<=18){
                System.out.println("It only took you" + numofguesses + "guesses");
                System.out.println("You got out before your option sank");

            }else{
                System.out.println("Took you long enough" + numofguesses + "guesses");
                System.out.println("Fish are dancing with your option");
            }
        }

        public static void main(String[] args) {
            DotComBust game = new DotComBust();
            game.setUpGame();
            game.startPlaying();
        }

}

Error

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at DotComBust.checkUserGuess(DotComBust.java:77)
at DotComBust.startPlaying(DotComBust.java:68)
at DotComBust.main(DotComBust.java:106)

Solution

  • I assume you may have another drawing thread running at the same time?

    In this case use a thread-safe implementation of the List called CopyOnWriteArrayList:

    private ArrayList<DotCom> dotComList = new CopyOnWriteArrayList<DotCom>();