Best Practices for Using Multi Level HashMap in Java

11,500

Solution 1

As long as they're properly abstracted, it's not that big of a deal, but you lead yourself down some nasty rabbit holes in terms of readability. Without abstraction, maintaining this becomes a nightmare that no developer would wish on another.

Essentially, what you're creating is a table of sorts; the first key is the primary key to gain access to further columns. On a simple one, two, or three-level design, this isn't terrible; you need three keys to get a single value. Provided that there's a convenient way to access it, like the below, it's not a terrible idea (although there are far better out there).

public interface Table<K1, K2, K3, V> {
    V get(K1 key1, K2 key2, K3 key3);
}

...However, it all depends on what you're actually doing with that data structure. If you find yourself attempting to iterate intermediate keys for values (that is, you're looking at Key 3 for the collection of all values between it and Key 5), you've got to rethink your business logic at that point. The data structure provided isn't flexible enough to handle all cases; more or less, it's used for simplistic indexing based on a set of values.

Alternatively, one could look into a Guava Table, as that does the same sort of thing, with a better interface to it (something like the one I have above).

Solution 2

I think doing HashMap within HashMap is bad practice, because in order to extend your HashMap to go deeper, will cost you both time and money. Going from 3 level depth Map to 5 level depth Map, you would essentially have to re-code your Class. Which will put a lot of technical debt when it comes to maintaining this program.

Declare the Initial Map somewhere

Map<String, MyHashedObject> HashKVP = new HashMap<String, MyHashedObject>();

Then have an Object to store additional maps.

class MyHashedObject {

    private Map<String, MyHashedObject> InternalKvp;

    public MyHashedObject() {
        this.InternalKvp = new HashMap<String, MyHashedObject>();
    }

    /*
    * Get the next level of our MyHashedObject object
    * @param HashKey
    * @return MyHashedObject result
    */
    public MyHashedObject findHashedObject(String HashKey) {
        MyHashedObject result = null;
        if(this.InternalKvp.containsKey(HashKey)) {
            result = this.InternalKvp.get(HashKey);
        }
        return result;
    }




}

This way, you can easily extend more levels to your HashMap by simply dumping more Objects into the InternalKvp.

This just a very basic example, but you can add more properties to the MyHashedObject (such as depth, parent_object etc). You could do something like Small-world network, to track the depth of each object.

This could also be done better, using a RedBlackTree or AVLTree to make it easier to traverse through the Maps.

Solution 3

Multi-level HashMaps are not necessarily bad, it depends on your algorithm. The bad thing is that it's more difficult to manage. Consider using interfaces (something like repository) for HasMap values, this may make your design cleaner. Other option is to use composite keys in a HashMap.

Share:
11,500

Related videos on Youtube

anzaan
Author by

anzaan

Updated on September 15, 2022

Comments

  • anzaan
    anzaan over 1 year

    We have a situation where we are ending up using multi-level hash maps; that is, a hash map inside of a hash map, three or four levels deep.

    Instinctively this felt wrong somewhere. I have read posts here that talks about how to iterate/use a multi-level hash map, but hardly any of them say what is the best practice for this.

    Why are multi level hash maps bad, and what would be the better design, if any?

    Here is the sample design of multi-level hash maps that we have:

    Map<String, Object1> map1;
    
    class Object1 {
        String version;
        Map<String,Object2> map2;
    }
    
    class Object2 {
        Map<String,List<Object3>> map4;
        Map<String,String> map5;
    }
    
  • Makoto
    Makoto almost 9 years
    I personally would presume that a data structure like this is regarded as a one-off. Tables have their place, but it's uncommon to see them a lot. By the way, HashKVP is kind of just hanging around in no-man's land.
  • classicjonesynz
    classicjonesynz almost 9 years
    Yeah it is in no-man's land, its just an example of the starting object.. which contains MyHashedObject.
  • Makoto
    Makoto almost 9 years
    So, I've had a moment to look at this a bit closer...could you explain what the difference is between this solution and what the OP has already provided? It kind of looks the same to me.
  • classicjonesynz
    classicjonesynz almost 9 years
    The difference is that, in order for OP to make his map 5 levels deep, he has to write 3 new objects, then reference those objects to his existing objects. (new Object4, Object5). All I have to do is write MyHashedObject Object4 = new MyHashedObject() then HashKVP.put(StringRef, Object4);. The difference is the time taken to do this (and the time it takes to maintain the existing code, and create new code).
  • Makoto
    Makoto almost 9 years
    Sorry, I'm not convinced that there's a difference. At some level (with a bit of indirection), you're still creating multiple maps, it's just with one object instead of several. You also don't enforce or guarantee any type flexibility, so flexibility is sacrificed for maintainability. The layer that the objects add is pretty thin.
  • classicjonesynz
    classicjonesynz almost 9 years
    It's a basic example, of a different way of declaring maps within maps, with less code (as stated in the answer, it can be extended to make it more abstract and concrete). Obliviously you wouldn't copy/paste this, and say job well done.
  • anzaan
    anzaan almost 9 years
    I went through the code of Guava Table implementation HashBasedTable which again uses data structure like Map<R, Map<C, V>>. But yes it provides better interface. I was hoping for some drastic change in data representation. Could you give an example of what you mean by proper abstraction for above design?
  • anzaan
    anzaan almost 9 years
    I couldn't really get how difficult it will be to manage if the code is properly structured. Could you elaborate on this - "using interfaces (something like repository) for HasMap values".
  • Konstantin Pavlov
    Konstantin Pavlov almost 9 years
    Try to write a unit test on a structure with nested maps and you will see how difficult is it. In this case you'll need an abstractions to simplify the logic.