Solved Getting top 10 kills

Discussion in 'Plugin Development' started by Tim_M, Jul 30, 2021.

  1. Offline

    Tim_M

    I'm making a plugin that keeps track of players kills, deaths etc. There are leaderboards with top kills and such. The simplest way is going through the config and checking. But let's imagine a server has had like 5k unique players. Then going through the config takes a stupid amount of time and lags the server. (It also has to be done everytime someone opens the leaderboard GUI). In order to recude I/O calls I made it so that when a server starts it copies all the data from the config into several HashMap which contain player's UUID and their kills/deaths etc. Whenever the data is changed the hashmap get's sorted with a function I made here:
    Code:
    public void sortKills()
        {
            HashMap<String, Integer> unordered = new HashMap<String, Integer>();
            HashMap<String, Integer> ordered = new HashMap<String, Integer>();
    
            unordered.putAll(kills);
        
            String playername;
            int highestvalue = 0;
            for (int i = 0; i < unordered.size(); i++)
            {
                for (Entry<String, Integer> e : unordered.entrySet())
                {
                    if (e.getValue() > highestvalue)
                    {
                        highestvalue = e.getValue();
                        playername = e.getKey();
                        ordered.put(playername, highestvalue);
                        unordered.remove(playername);
                    }
                }
            }
        
            kills.clear();
            kills.putAll(ordered);
        }
    
    My problem is that sorting the data when the data changes is that it causes:
    Code:
    java.util.ConcurrentModificationException
    
    Is there any way to work around this?

    EDIT
    if it matters the error happens at:
    Code:
    for (Entry<String, Integer> e : unordered.entrySet())
    
    Any answers are appreciated.

    Issue solved.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jul 30, 2021
  2. Offline

    c7dev

    ConcurrentModificationException is called when you edit a sequence at the same time you iterate through it. For example, the following code would cause a Concurrent Modification Exception:
    Code:
    List<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");
    list.add("c");
    for (String s : list) list.remove(s);
    To fix it, you could change the line to
    Code:
    for (String s : list.toArray(new String[list.size()])) list.remove(s);
    or anything that makes a duplicate list to iterate through

    As for efficiency in getting the leaderboards, you should have them only periodically update (maybe every 10 minutes), and use a sorting algorithm run over an asynchronous bukkit runnable. That way, when a player looks at the leaderboards, it just shows them the pre-calculated values for 1st place, 2nd place, etc.
     
    KarimAKL and davidclue like this.
  3. Offline

    KarimAKL

    Just to add on (this will already work); but you could also create an empty array:
    Code:Java
    1. list.toArray(new String[0])
     
  4. Offline

    Tim_M

    Thank you for the responses! I solved this issue by just sorting the list when the data changes. I forgot to make an async schedule call so thanks for that!
     

Share This Page