Solved ConcurrentModificationException

Discussion in 'Plugin Development' started by dlange, Jun 20, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    dlange

    I am getting a ConcurrentModificationException here:

    Code:
                    for (String s1 : serverPlayers.keySet()) {
                        for (String s2 : serverPlayers.get(s1).keySet()) {
                            try {
                                int op = Core.plugin.sqlManager.getOnlinePlayers(s1);
                                HashMap<String, Integer> gmPlayers = new HashMap<String, Integer>();
                                gmPlayers.put(s2, op);
                                serverPlayers.remove(s1);
                                serverPlayers.put(s1, gmPlayers);
                            } catch (SQLException e) {
                                e.printStackTrace();
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    }
    At this line exactly:
    Code:
                   for (String s1 : serverPlayers.keySet()) {
    Does anyone know what causes this? Thanks for any help :)
     
  2. Offline

    Lilret123

    @dlange you cant modify a collection while iterating over it

    try creating a for loop that ends at the size of the collection
    Code:
     for (int i = 0; i < {collection}.size; i++) {
                      object object = collection.get(0);
               }
     
  3. Offline

    Ratismal

    @dlange Another thing you could do is make a copy of the collection, and iterate through the copy instead.
    Code:
    List<String> serverPlayersCopy = new ArrayList<>();
    serverPlayersCopy.addAll(serverPlayers);
    for (String s1 : serverPlayersCopy.keySet()) {
      for (String s2 : serverPlayersCopy.get(s1).keySet()) {
        try {
          int op = Core.plugin.sqlManager.getOnlinePlayers(s1);
          HashMap<String, Integer> gmPlayers = new HashMap<String, Integer>();
          gmPlayers.put(s2, op);
          serverPlayers.remove(s1);
          serverPlayers.put(s1, gmPlayers);
        } catch (SQLException e) {
          e.printStackTrace();
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        }
      }
    }
    
    That way you're not iterating through the collection that you're modifying.
     
  4. Offline

    Konato_K

    @dlange Use an iterator insteads, you should be able to call Iterator#remove in it while iterating as long as the Collection is not unmodifiable.
     
  5. Offline

    dlange

    Sweet thanks! I fixed it doing this:

    Code:
                    HashMap<String, HashMap<String, Integer>> serverPlayersCopy = (HashMap<String, HashMap<String, Integer>>) serverPlayers.clone();
                    for (String s1 : serverPlayersCopy.keySet()) {
                        for (String s2 : serverPlayersCopy.get(s1).keySet()) {
                            try {
                                int op = Core.plugin.sqlManager.getOnlinePlayers(s1);
                                HashMap<String, Integer> gmPlayers = new HashMap<String, Integer>();
                                gmPlayers.put(s2, op);
                                serverPlayers.remove(s1);
                                serverPlayers.put(s1, gmPlayers);
                            } catch (SQLException e) {
                                e.printStackTrace();
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }
                    }
     
  6. Offline

    teej107

    Not the best of way to achieve this.

    @Konato_K's suggestion was good.
     
Thread Status:
Not open for further replies.

Share This Page