Решатель Судоку с Исключением в потоке "main" java.util.ConcurrentModificationException на его Итераторе - PullRequest
0 голосов
/ 07 июля 2011

Я получаю следующие ошибки:

     Exception in thread "main" java.util.ConcurrentModificationException 
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:810)
        at java.util.HashMap$KeyIterator.next(HashMap.java:845)
        at sudoku.Main.solve2(Main.java:143)
        at sudoku.Main.next2(Main.java:168)
        at sudoku.Main.solve2(Main.java:153)
        at sudoku.Main.main(Main.java:284) 

Я не понимаю сообщений об ошибках java.util.HashMap$KeyIterator.next и java.util.HashMap$HashIterator.nextEntry, поскольку я не могу получить набор ключей для HashSet в явном виде. Я предположил, что итератор проходит набор ключей по умолчанию.

Я не использую потоки, просто рекурсивные вызовы. Что тут происходит?

 static void solve2(int row, int col, int [][]grid,  ArrayList<HashSet<Integer>> availableNumsInRows,
          ArrayList<HashSet<Integer>> availableNumsInColumns){

     if (row>=grid.length){

           System.out.println("solution found");
            printSolvedGrid(grid);

            System.out.println("move count for this sudoku is " + moveCounter);
            moveCounter=0; //reset counter
           return;


       }

       if( grid[row][col] != 0 ){
            next2( row, col, grid, availableNumsInRows, availableNumsInColumns ) ;
       }

       else {
         // Find a valid number for the empty cell

         Iterator <Integer> iterator = availableNumsInRows.get(row).iterator();


         for( int num = iterator.next() ; iterator.hasNext(); num = iterator.next())
         {
            if( checkRow(row,num,grid) && checkCol(col,num,grid) && checkBox(row,col,num,grid) )
            {
               grid[row][col] = num ;
               availableNumsInRows.get(row).remove(new Integer(num));
               availableNumsInColumns.get(col).remove(new Integer(num));
               moveCounter++;

               //printSolvedGrid(grid);
               next2( row, col, grid, availableNumsInRows, availableNumsInColumns );

            }
         }

         grid[row][col] = 0 ;
       }

  }

  //helper function for the first solution approach
  public static void next2( int row, int col, int [][] grid ,  ArrayList<HashSet<Integer>> availableNumsInRows,
          ArrayList<HashSet<Integer>> availableNumsInColumns )
   {
      if( col < 8 ) //pass to next col
         solve2( row, col + 1, grid, availableNumsInRows, availableNumsInColumns) ;
      else //pass to next row
         solve2( row + 1, 0, grid, availableNumsInRows, availableNumsInColumns) ;
   }

Редактировать:

Я изменил код на:

   while (iterator.hasNext())
             {

                num=iterator.next();

                if( checkRow(row,num,grid) && checkCol(col,num,grid) && checkBox(row,col,num,grid) )
                {
                   grid[row][col] = num ;

                   iterator.remove();

                   moveCounter++;


                   next2( row, col, grid, availableNumsInRows, availableNumsInColumns );

                }

             }

и я все еще получаю ConcurrentModificationException, почему это?

Exception in thread "main" java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:810)
        at java.util.HashMap$KeyIterator.next(HashMap.java:845)
        at sudoku.Main.solve2(Main.java:148)
        at sudoku.Main.next2(Main.java:175)
        at sudoku.Main.solve2(Main.java:137)
        at sudoku.Main.next2(Main.java:175)
        at sudoku.Main.solve2(Main.java:159)
        at sudoku.Main.next2(Main.java:175)
        at sudoku.Main.solve2(Main.java:137)
        at sudoku.Main.next2(Main.java:175)
        at sudoku.Main.solve2(Main.java:159)
        at sudoku.Main.next2(Main.java:175)
        at sudoku.Main.solve2(Main.java:159)
        at sudoku.Main.main(Main.java:291)
Java Result: 1

Ответы [ 5 ]

1 голос
/ 07 июля 2011

Вы изменяете Карту, перебирая ее.

Вместо этого

availableNumsInRows.get(row).remove(new Integer(num));

Попробуйте это

iterator.remove();

Этого может быть достаточно.

1 голос
/ 07 июля 2011

Вы перебираете карту хеша, но также изменяете ее в том же цикле.Это приведет именно к этому исключению.

Вы можете избежать этого в течение одного звонка , вызвав iterator.remove() вместо availableNumsInRows.get(row).remove(new Integer(num));

Однако вы повторяете, создаваяновый итератор каждый раз.Если вы удалите что-либо с помощью одного из итераторов в вызове nested , то при переходе к итерации в вызове external у вас возникнет та же проблема.

Одним из вариантов будет упрощение кода, чтобы избежать повторения таким образом;другой - использовать один итератор и передавать его.

0 голосов
/ 07 июля 2011

Вы не должны добавлять / удалять элементы в / из HashSet или HashMap (кстати, это базовый класс для HashSet во время итерации. Это вызывает исключение.

Использование итератора длявместо этого удалите предметы, как предложил Джон Скит.

0 голосов
/ 07 июля 2011

Нельзя удалить элемент из Collection (частью которого является ArrayList), когда вы выполняете итерацию с Iterator.Вы можете удалить элемент из итератора, используя iterator.remove() вместо availableNumsInRows.get(row).remove(new Integer(num)).

0 голосов
/ 07 июля 2011

Вам нужно изменить коллекцию с помощью обращений к ее итератору во время итерации по ней, иначе произойдет ConcurrentModificationException:

...
availableNumsInRows.get(row).remove(new Integer(num));
availableNumsInColumns.get(col).remove(new Integer(num));
...
...