Solved HashMaps problems

Discussion in 'Spigot Plugin Development' started by Valenwe, Mar 30, 2020.

  1. Hello!

    I want to use Hashmaps to get a claim system in my plugin. So first I set it for solo players, and it works fine. But I now want to implement for teams.

    So basically my first Hashmap is <UUID><Location>. And then I changed it as <Location><List <UUID>>. But it makes the whole thing weird.

    So in the situation where I want to check if for a uuid given, there is a pre existing claim, and then return his location. Here is my code:

    public Location checkUUID(UUID uuid_given) {
    for (List <UUID> list_uuid : Main.map.values()) {
    for(int i = 0; i < list_uuid.size() ; i++) {
    if (list_uuid == uuid_given) {
    return (Location) Main.map.get(list_uuid);
    }
    }
    } return null;
    }

    Problem is that list_uuid has an error message: "The type of the expression must be an array but it resolved to List<UUID>". For me List<UUID> is an array, and I don't understand my mistake then...

    Thanks for your help!
     
  2. you are comparing list_uuid with uuid_given.
    First of all, in Java, you generally only compare using == if the expression is a primitive or enum. If it's an object, you use Object#equals() instead.
    Then, you are comparing a list with a UUID. You are iterating over each entry of the list, but you are never using any entry of that list. Either use
    Code (Text):
    list_uuid.get(i);
    or use the same loop that you use to iterate over the values of the map:
    Code (Java):
    for(UUID uuid: list_uuid) {
        //...
    }
    Also, since this structure (Map<T,List<T>> is so common, you should instead use Google's Multimap instead. You can then do a simpler check using Multimap#containsValue(V), resp. Multimap#containsKey(K), depending on your implementation.
    You'll never need to cast your result like that, that's the point of generics. Map#get(T) returns the value associated with the key, in your case a list of UUID's.
    You haven't created an array anywhere, you only have lists.
    Also, it seems like you are abusing static and public here. You should work with dependency injection and getters to get the map.
     
  3. Thanks for your reply!

    I'm new to Java, so i'm wondering how can I use those multimaps, and also what do you mean by "dependency injection and getters".

    I'll first try to use the .get(i), but I guess multimaps are better.
     
  4. Multimaps are (as I said) Maps, that enable fast and more readable access to data structures that look like this:
    Code (Text):
    Map<T,Collection<T>> aMap = new HashMap<>();
    You can create a simple Multimap for your case like this:
    Code (Java):
    Multimap<Location,UUID> uuids = HashMultimap.creata();
    .
    You can insert values like this:
    Code (Text):
    uuids.put(location, uuid);
    Just like there is the rule concerning maps that a map cannot have the same key twice; a multimap cannot have the same key-value-pair twice. So this is not okay for a map, but works for a multimap:
    Code (Text):
    Location a = new Location(world, 1, 1, 1);
    UUID uuid1 = UUID.randomUUID();
    UUID uuid2 = UUID.randomUUID(); // assuming uuid2 is not uuid1 by sheer coincidence

    map.put(a, uuid1);
    map.put(a,uuid2); // only contains uuid1

    multimap.put(a, uuid1);
    multimap.put(a, uuid2); //contains uuid1 and uuid2
    However, this does not work for a Multimap:
    Code (Java):

    multimap.put(a, uuid1);
    multimap.put(a, uuid1); //contains only uuid1 once.
     
    Try understanding why it didn't work before you try something that is generally considered to be more "difficult" (depending on how you look at it).
    The stuff about static and public:
    This has been discussed here so many times, so I'm not gonna go into detail. What you have right now is probably something like this:
    Code (Java):
    public static Map<Location,List<UUID>> map = new HashMap<>();
    1) map is a horrible name, you should give it a name that represents what the map contains
    2) getters:
    Code (Java):
    private static Map<Location,List<UUID>> map = new HashMap<>();
    public static Map<Location,List<UUID>> getMap() {
        return map;
    }
    This might seem nonsensical and I'm not going into detail on why this is better. Just search for getters and setters online.
    3) static
    Also, not going into detail, but you should never use static unless you know exactly why you are using it.
    Dependency injection is basically (there's a lot more behind, just google this as well) passing a reference to some class that you depend on (in your case the main class, which is a horrible name as well) inside a constructor to a class that depends on it. take this command-class as an example:
    Code (Java):
    public class CommandTest {
       
        // again, private and not static
        private Plugin plugin;

        // Constructor
        public CommandTest(Plugin plugin) {
            this.plugin = plugin;
        }
    }
    You can now access methods of your dependent object (in this case, the instance of your plugin-class) using
    Code (Java):
    plugin.someMethod();
    Again, if you want to know why you should do it, google it or read the beginners programming guide in this forum.
     
    • Like Like x 1