I'm getting the following errors:
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)
I don't understand the java.util.HashMap$KeyIterator.next
and java.util.HashMap$HashIterator.nextEntry
error messages, as I'm not able to get the keySet for a HashSet
explicitly I assumed the Iterator was going through the keySet by default.
I'm not using threads, just recursive calls. What's going on here?
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) ;
}
Edit:
I changed the code to:
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 );
}
}
and I'm still getting the ConcurrentModificationException
, why is this?
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
You're iterating over the hash map but also modifying it in the same loop. That will cause exactly this exception.
You can avoid this within one call by calling iterator.remove()
instead of availableNumsInRows.get(row).remove(new Integer(num));
However, you're recursing, creating a new iterator each time. If you remove something via one of the iterators in the nested call, then when you come to iterate in the outer call, you'll have the same problem.
One option would be to simplify the code to avoid recursing in this way; another would be to use a single iterator and pass that around.