Search code examples
javajtree

JTree out of Hashmap


I have a (Hash)Map called treefile with sample content:

treefile.put("Adhesive Tapes", "Mechanical  Components|Mechanical Incidentals|Fastening Elements");
treefile.put("Bayonet Fitting, Snap Locks, Spring Locks", "Mechanical  Components|Mechanical Incidentals|Fastening Elements");

The value of treefile is the path for the JTree and the key is the product. I'm iterating over the Map with:

for (Map.Entry<String, String> entry : file.entrySet()) {
        String key = entry.getKey();
        String values[] = entry.getValue().split("\\|");
        DefaultMutableTreeNode keyn = new DefaultMutableTreeNode(key);
        for (String k : values) {
            DefaultMutableTreeNode n = new DefaultMutableTreeNode(k);
            keyn.add(n);
        }
        top.add(keyn);
}

DefaultMutableTreeNode top = new DefaultMutableTreeNode(firstn);

The problem now is, that the JTree shows me each "top.add(keyn)" as a new node instead of adding it to the existing one...

How can i fix this? So that if the node exists its added to this one?

I want to see the JTree like:

Root
|
Mechanical Components
    |
    Mechanical Incidentals
        |
        Product A
        |
        Product B

and not like its now:

Root
|
Mechanical Components
    |
    Mechanical Incidentals
    |       |
    |      Product A
    Mechanical Incidentals
            |
           Product B

Solution

  • Instead of blindly adding new nodes, you need to look for a matching ancestor node as you add leaf nodes.

    Your keys represent leaf nodes, that is, nodes which should have no children, so you definitely should not be doing keyn.add(n). Rather, you should create nodes as needed for the tree path represented by the split value. The “as needed” part is important if you want to be able to place multiple nodes under the same parent.

    for (Map.Entry<String, String> entry : file.entrySet()) {
        String key = entry.getKey();
        String values[] = entry.getValue().split("\\|");
    
        DefaultMutableTreeNode parent = top;
        for (String k : values) {
            DefaultMutableTreeNode n = null;
    
            Enumeration<?> e = parent.children();
            while (e.hasMoreElements()) {
                n = (DefaultMutableTreeNode) e.nextElement();
                if (k.equals(n.getUserObject())) {
                    // Existing node matches; use that one.
                    break;
                }
                n = null;
            }
    
            if (n == null) {
                // No existing node matches;  add it.
                n = new DefaultMutableTreeNode(k);
                parent.add(n);
            }
    
            parent = n;
        }
    
        DefaultMutableTreeNode keyn = new DefaultMutableTreeNode(key);
        parent.add(keyn);
    }
    

    There are more efficient ways to do this. For example, instead of relying on DefaultMutableTreeNodes, you can create your own implementation of TreeNode which uses a LinkedHashMap<String, TreeNode> internally, which would allow you to look up a TreeNode for a particular String more easily.

    Also, be aware that not all Map implementations maintain consistent order. Your Map<String, String> should be a SortedMap or LinkedHashMap.