简体   繁体   中英

Iterate HashMap one full time, with no repeats

My goals:

  • Have it even more normalized. (more similar wait times - linear growth)
  • Scale up to XXX and maybe even XXXX number of monsters and npcs.
  • Have all of you Java gurus out there give me some ideas :D

My issues are the following:

  • It never hits the second iteration loop(npc)
  • The 'wasted' time is too random; there will be hundreds(if not more) of mobs/npcs to iterate through, this solution will not scale at all
  • I have many other 'events' my server will do in the main loop, some of which use the same HashMaps, hence the use of ConcurrentHashMap(calculate hit damage/etc)

Code: I hope this is SSCCE enough. I tried to trim the fat as much as possible...

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class WaitTime {

    static ConcurrentHashMap<String, Integer> mobInstanceMap = new ConcurrentHashMap<String, Integer>();
    static ConcurrentHashMap<String, Integer> npcInstanceMap = new ConcurrentHashMap<String, Integer>();

    public static void main(String[] args){
        mobInstanceMap.put("mob1", 0);
        mobInstanceMap.put("mob2", 0);
        mobInstanceMap.put("mob3", 0);
        npcInstanceMap.put("npc1", 0);
        npcInstanceMap.put("npc2", 0);
        npcInstanceMap.put("npc3", 0);
        while(true){
            updateEntityLocations();
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static void updateEntityLocations() {
        long entityMovementLoopStartTime = System.nanoTime();
        Iterator<Entry<String, Integer>> it = mobInstanceMap.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, Integer> mobEntity = it.next();
            String mobName = mobEntity.getKey();
            int lastWalkTime = mobEntity.getValue();
            int mobWalkSpeed = 4000;
            long walkWaitTime = lastWalkTime;
            long elapsedTime = (long) ((System.nanoTime() - entityMovementLoopStartTime) / 100.0);
            walkWaitTime += elapsedTime;

            if (walkWaitTime >= mobWalkSpeed){
                System.out.println("Wasted time(walking)(" + mobName + "): " + (walkWaitTime - mobWalkSpeed));

                //mobInstanceMap.put(mobName, 0);
                mobInstanceMap.replace(mobName, 0);
            } else {  //!(walkWaitTime >= walkSpeed)
                //mobInstanceMap.put(mobName, (int) walkWaitTime);
                mobInstanceMap.replace(mobName, (int) walkWaitTime);
            }
        }

        Iterator<Entry<String, Integer>> it1 = npcInstanceMap.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, Integer> npcEntity = it1.next();
            String npcCoords = npcEntity.getKey();
            int lastWalkTime = npcEntity.getValue();
            int npcWalkSpeed = 4000;
            long walkWaitTime = lastWalkTime;
            long elapsedTime = (long) ((System.nanoTime() - entityMovementLoopStartTime) / 100.0);
            walkWaitTime += elapsedTime;

            if (walkWaitTime >= npcWalkSpeed){
                System.out.println("Wasted time(walking)(" + npcCoords + "): " + (walkWaitTime - npcWalkSpeed));

                npcInstanceMap.put(npcCoords, 0);
            } else {  //!(walkWaitTime >= walkSpeed)
                npcInstanceMap.put(npcCoords, (int) walkWaitTime);
            }
        }   
    }
}

Console:

Wasted time(walking)(mob2): 58
Wasted time(walking)(mob1): 1983
Wasted time(walking)(mob3): 2288
Wasted time(walking)(mob3): 266
Wasted time(walking)(mob1): 122
Wasted time(walking)(mob3): 232
Wasted time(walking)(mob2): 23
Wasted time(walking)(mob1): 674
Wasted time(walking)(mob3): 27
Wasted time(walking)(mob1): 159
Wasted time(walking)(mob3): 1723
Wasted time(walking)(mob2): 119
Wasted time(walking)(mob1): 676
Wasted time(walking)(mob3): 1698
Wasted time(walking)(mob3): 3983
Wasted time(walking)(mob1): 182

As you can see if you run it with put(commented out) instead of replace it runs slightly slower and more erratic.

You'll kick yourself, but the second loop references the first iterator.

Iterator<Entry<String, Integer>> it1 = npcInstanceMap.entrySet().iterator();
while (it.hasNext()) {
    ...
}

Also, as this answer suggests, I propose not using an iterator.

for(String mob : mobInstanceMap.keySet()){
    String mobName = mob;
    int lastWalkTime = mobInstanceMap.get(mob);
    int mobWalkSpeed = 4000;
    long walkWaitTime = lastWalkTime;
    long elapsedTime = (long) ((System.nanoTime() - entityMovementLoopStartTime) / 100.0);
    walkWaitTime += elapsedTime;

    if (walkWaitTime >= mobWalkSpeed){
        System.out.println("Wasted time(walking)(" + mobName + "): " + (walkWaitTime - mobWalkSpeed));

        mobInstanceMap.put(mobName, 0);
    } else {  //!(walkWaitTime >= walkSpeed)
        mobInstanceMap.put(mobName, (int) walkWaitTime);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM