Saving 2 variables to a player's name using HashMaps

Discussion in 'Plugin Development' started by MeneXia, Dec 22, 2011.

Thread Status:
Not open for further replies.
  1. I'll post the code, then explain afterwards.
    PHP:
    public Map<StringMap<ShortInteger>> scrollHM = new HashMap<StringMap<ShortInteger>>();
        public 
    Map<ShortIntegeramtuses = new HashMap<ShortInteger>();
    I've got a CommandExecutor set up, and this is how the plugin goes:
    When a player does /gs use, it will get the item in hand's durability (short), and an integer from a configuration. The (short) gets added, and the integer is either created or added onto the existing value. This gets saved in "amtuses."

    I realized that I couldn't continue with this setup, because "amtuses" cannot contain duplicate keys. Thus, any player can be able to access and change the integer in amtuses.

    Is there a way so that the Short and Integer can be directly attributed to the player's name?
    (i.e. each player has his own short and integer values, rather than this setup, which all falls under an overall map?)
    If this needs extra clarification, please tell me.
     
  2. public Map<String, Map<Short, Integer>> amtuses = new HashMap<String, HashMap<Short, Integer>>();
     
  3. @V10lator Thanks, I'll give this a shot and get back to you.
     
  4. Offline

    halley

    You've described a hash of hashes, but I think you're just asking for a hash of data. What does the short represent, an item type? What does the integer represent, a durability? And most importantly, does Player Bob need to keep more than one short value?
     
    Father Of Time likes this.
  5. Offline

    Father Of Time

    As Halley has stated, depending on what you are storing you may be over doing it.

    For instance, if you wanted to keep a single record per player I would do something like:

    Code:
    Map<String,CustomClass> MyMap = new HashMap<String, CustomClass>();
    Then create a simple class that stores the data you want to link to the player:

    Code:
    public class CustomClass
    {
        private Short value1;
        private Integer value2;
    
        public CustomClass( Short val1, Integer val2 )
        {
            value1 = val1;
            value2 = val2;
        }
    {
    This way you have 1 "record class" per player, and inside that record class you can store any necessary information. I've found that embedding collection inside collection, although sometimes necessary, often leads to complications down the road, such as with serializing.

    I hope this helps, sorry if my ranting is completely off topic. :p
     
    skore87, bergerkiller and desht like this.
  6. Offline

    bergerkiller

    Yup, whenever I end up storing more than one 'value' per key, I make a custom class to store both of them. I usually add static methods in the same custom class with a static hashmap to access.
    Code:
        private static HashMap<String, TrainProperties> properties = new HashMap<String, TrainProperties>();
        public static TrainProperties get(String trainname) {
            if (trainname == null) return null;
            TrainProperties prop = properties.get(trainname);
            if (prop == null) {
                return new TrainProperties(trainname);
            }
            return prop;
        }
        public static boolean exists(String trainname) {
            return properties.containsKey(trainname);
        }    
    One class with all your data - it makes everything a lot simpler.
     
    Father Of Time likes this.
  7. Yes, Player Bob needs to store more than one short value, so I think bergerkiller's and Father Of Time's suggestions of creating a custom class to store the data would best suit my situation.
     
  8. Offline

    halley

    If Player Bob needs more than one Short, then you do need a hash of hashes. You can actually skip the custom class that bergerkiller/Father/I were suggesting, and use V10lator's approach directly. Or you could put the inner Map<Short,Integer> inside the custom class if you like. I just wasn't sure you needed the inner map from your description.
     
    MeneXia likes this.
  9. Offline

    bergerkiller

    @halley But I do recommend adding some sort of function to return the hashmap then.
    Code:
    private Map<String, Map<Short, Integer>> scrollHM = new HashMap<String, Map<Short, Integer>>();
    public Map<Short, Integer> getHM(String playername) {
        Map<Short, Integer> map = scrollHM.get(playername);
        if (map == null) {
            map = new HashMap<Short, Integer>();
            scrollHM.put(playername, map);
        }
        return map;
    }
    public Map<Short, Integer> getHM(Player player) {
        return getHM(player.getName());
    }
    public int getHMCount(Player player, short durability) {
        Integer value = getHM(player).get(durability); //not sure if this can be null, may need contains check above
        if (value != null) return (int) value;
        return 0;
    }
    May need some correction, I wrote this at 1:58 AM in the reply field :)
     
  10. Offline

    halley

    Yes, I hate it when ALL of the code is stuck inside the bukkit callback method; making useful little functions is a hard thing to get new coders to understand.
     
  11. Added those, works great, and my code reduced in size (due to having long lines of repetitive code from referencing the hashmap directly, lol). Well, I'd consider this a learning experience. Thanks to all who replied for the help. :)
     
Thread Status:
Not open for further replies.

Share This Page