Wrong practice of using nested HashMaps?

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

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

Initially, I designed it in such a way that several HashMap are used to support it. But then I quickly realized that updating becomes an extremely difficult task.

Having multiple HashMap means that I have to handle uniqueness in different ways. For example, A1.1 may exist inside the root of a B node. therefore they need to add A to A1.1 so that I can ensure uniqueness. Now, if I need to change the value of A , then I have big problems, since I used this to qualify all the keys in A as A_A1.1

Now I think I can use Nested HashMaps for this. So the code for this would be:

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

How much is this practice? I have a lot of bookkeeping because I will use nested hashes, but at least problems with CRUD and uniqueness are handled by myself.

If this is not normal, can anyone suggest another better structure that I can use?

+8
java hashmap data-structures
source share
2 answers

You obviously want to model a tree. This tree is not necessarily associated with a TreeMap explicitly. And admittedly, I don’t see how TreeMap can help represent the whole structure (although it can be used in separate nodes of the tree).

You can 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())); } 

(quick sketch only)

Then you could build a 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 move around the hierarchy, and maintaining relationships would be fairly easy.

I did not quite understand what you said about "uniqueness." In any case, in such a tree, each node is uniquely identified by its path. You can even create a utility method, for example

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

for quick access to an object through a sequence of node names.


Aside: as already indicated, deeply nested cards (or lists or sets) are doubtful. But no matter what, you should always use interfaces, for example, in

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

This may be normal for some use cases, but depending on what you want to model (and especially when there is another layer), it may already be inconvenient.

+4
source share

Your suggestion is not recommended.

Assuming your requirements should be able to select an item in O (log (n)) time based on the key. I would suggest doing one of the following as the best solution to this problem:

  • Use TreeMap, or if you need concurrency, use ConcurrentSkipListMap (this will be my number 1 to solve your problem).
  • Let TreeSet contain keys and a separate HashMap for mapping between keys and values
  • Create a class that encapsulates the mapping (i.e., Decorator HashMap) that will recursively handle a unique key check (again, the first approach is more desirable)
+2
source share

All Articles