Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a bad practice to use nested HashMaps?

Let me explain my scenario. I have some hierarchy that I need to maintain. Find below an image that shows this hierarchy. I will explain after the image.

   A
   |          +--> A1.1 ---> X
   |          | 
   +--> A1 ---+--> A1.2 ---> Y
   |          |
   |          .
   +--> A2    .
   .
   .
  • From A to A1, A2... it is a one to many relationship
  • From A1 to A1.1, A1.2... it is a one to many relationship
  • From A1.1 to X and A1.2 to Y it is a one to one relationship.

Initially I had designed it in such a way that it uses multiple HashMaps to maintain this. But then I quickly realized that updating becomes an extremely hard job.

Having multiple HashMaps means that I have to handle the uniqueness across the different relationships myself. For example A1.1 can exist within a root B node as well. so im having to append A to A1.1 so that I can ensure uniqueness. Now if i have to modify the value A then I am in major trouble since I have used that to qualify all keys within A as A_A1.1

Now i'm thinking that I can use Nested HashMaps for this. So the code for this becomes:

HashMap<String, HashMap<String, HashMap<String, CustomObject>>> _worldsBiggestHash; 

Is this practice ok? I do have a lot of bookkeeping to do since I'll be using nested hashes but at least CRUD and uniqueness problems handles itself.

If this isn't okay, could anyone suggest another better structure that I can use?

like image 789
Shrayas Avatar asked Mar 23 '14 06:03

Shrayas


People also ask

Can you have a nested HashMap?

A nested HashMap is Map inside a Map. The only difference between a HashMap and a nested HashMap is: For HashMap , the key or the value can be of any type (object). For Nested HashMap , the key can be of any type (object), but the value is another HashMap object only.

Are HashMaps efficient?

HashMap, being a hashtable-based implementation, internally uses an array-based data structure to organize its elements according to the hash function. HashMap provides expected constant-time performance O(1) for most operations like add(), remove() and contains(). Therefore, it's significantly faster than a TreeMap.

Can we use Map inside Map in Java?

In Java, Map is an interface that maps keys to values. Sometimes it is required to implement Map of Map (nested Map). Nested Map is used in many cases, such as storing students' names with their Ids of different courses.

Can I put a HashMap in a HashMap?

Method 2: Using putAll(k, v) Method. Map. putAll(k,v) method is used to copy one HashMap to another empty HashMap.


2 Answers

You obviously want to model a tree. This tree is not necessarily related to a TreeMap explicitly. And admittedly, I don't see how a TreeMap could help to represent the whole structure (although it could be used in the individual tree nodes).

You could create a class like this

class Node 
{
    private final String name;
    private final Map<String, Node> children;
    private final CustomObject customObject;

    Node(String name, CustomObject customObject)
    {
        this.name = name;
        this.children = new LinkedHashMap<String, Node>();
        this.customObject = customObject;
    }

    String getName()
    {
        return name;
    }

    void addChild(Node child) 
    {
        children.put(child.getName(), child);
    }

    void removeChild(String name)
    {
        children.remove(name);
    }

    Node getChild(String name)
    {
        return children.get(name);
    }

    Set<Node> getChildren()
    {
        return Collections.unmodifiableSet(
            new LinkedHashSet<Node>(children.values()));
    }

(only a quick sketch)

Then you could build the hierarchy like this

Node root = new Node("", null);
Node a1 = new Node("A1", null);
Node a2 = new Node("A2", null);
root.addChild(a1);
root.addChild(a2);

Node a11 = new Node("A11", x);
Node a12 = new Node("A12", y);
a1.addChild(a11);
a1.addChild(a12);

This would already allow you to navigate in the hierarchy, and maintaining the relationships would be quite easy.

I did not completely understand what you said about the "uniqueness". In any case, in such a tree, each node is uniquely identified by the path. You could even create a utility method like

CustomObject c = root.find("A", "A1", "A11");

to quickly access an object via the sequence of node names.


An aside: As it was already pointed out, deeply nested maps (or lists or sets) are questionable. But regardless of that, you should always use interfaces, like in

Map<String, Map<String, CustomObject>> maps;

This could be OK for certain use-cases, but depending on what exactly you want to model (and particularly, when there is another layer), this may already be inconvenient.

like image 117
Marco13 Avatar answered Oct 22 '22 20:10

Marco13


Your suggestion is not advisable.

Under the assumption that your requirements are to be able to fetch an item in O(log(n)) time based on a key. I would suggest doing either of the following as a better solution to this problem:

  1. Use a TreeMap, or if you need concurrency, use ConcurrentSkipListMap (this would be my number 1 choice for solving your problem)
  2. Have a TreeSet to contain the keys, and a separate HashMap to map between the keys and values
  3. Create a class that encapsulates the mapping (i.e. a HashMap Decorator), which will handle the unique key checking recursively (again, the first approach is more desirable)
like image 40
ethanfar Avatar answered Oct 22 '22 20:10

ethanfar