Search code examples
javahashmap

Why are multiple hashmaps being populated instead of 1 when storing hashmaps inside of a hashmaps?


I'm using the spigot api in Java to create a plugin (for minecraft) and to make cooldowns I've stored hashmaps inside of a hashmap. The outer hashmap is:

Map<String, Map<UUID, Long>> itemCooldowns = new HashMap<>();

When I try to add to a certain map inside the outer map (the problem isn't the cdId, I've checked):

itemCooldowns.get(cdId).put(p.getUniqueId(), System.currentTimeMillis() + cdTime);

It adds it to the correct map (with the key totem_of_storms_1) and also to another map (with the key totem_of_storms_2).

Another example of when this happens is if cdId is totem_of_time_2 it will add to totem_of_time_1 as well.

I have checked that it is this line that is adding to multiple hashmaps itemCooldowns.get(cdId).put(p.getUniqueId(), System.currentTimeMillis() + cdTime); but I have no idea why


Solution

  • When you have an object referenced in multiple place, modifying it from one access point will make it visible from any other access point.


    A very simple example can be done with a List

    List<Integer> a = Arrays.asList(1, 2, 3, 4);
    List<Integer> b = a;
    
    System.out.println(b); // [1, 2, 3, 4]
    a.set(1, 123);
    System.out.println(b); // [1, 123, 3, 4]
    

    Your case is a bit more complex with stays the same (I replaced UUID by String for visibility)

    Map<String, Map<String, Long>> items = new HashMap<>();
    
    Map<String, Long> m1 = new HashMap<>(Map.of("a", 123L));
    itemCooldowns.put("a", m1);
    
    Map<String, Long> m2 = new HashMap<>(Map.of("b", 456L)); // put m2 on 2 different keys
    items.put("b", m2);
    items.put("c", m2);
    
    System.out.println(itemCooldowns); // {a={a=123}, b={b=456}, c={b=456}}
    
    items.get("c").put("123", 789L);
    System.out.println(items);         //{a={a=123}, b={b=456, 123=789}, c={b=456, 123=789}}
    
    /* Modifying from access point 'c' make it also accessible from access point 'b'
    items -> a=m1
          -> b=m2
          -> c=m2