0

I have a Map<List<String>,Integer> where each entry is a path (List<String>) and a count

Ex:

["a1", "a2", "a3"] => 4
["a1", "a2"] => 2
["b1", "b2", "b3"] => 3
["b1"] => 4
["b1", "b2"] => 3
["c1", "c2", "c3", "c4"] => 5

I want to output a tree with count for each node

Tree:

- ROOT
-- a1 : 6
--- a2 : 6
---- a3 : 4
-- b1 : 7
--- b2 : 3
-- c1 : 5
--- c2 : 5
---- c3 : 5
----- c4 : 5

JSON Structure:

{
    "name": "",
    "count": "",
    "children": [
        {
            "name": "",
            "count": "",
            "children": []
        }
    ]
}

What can be the most efficient data-structure and then how to use it in this case (the tree should be then serialized into a JSON tree)?

10
  • how is the tree to be serialized in JSON. Can you give an example? Why the keys are lists, not single values? Why the different number of dashes in front of the different keys? Commented Jan 11, 2013 at 13:39
  • Your original structure seems way to complicated, any reason why you have opted for such a structure instead of a more traditional tree structure using Nodes? Commented Jan 11, 2013 at 13:44
  • Can you post an example of the expected JSON? Commented Jan 11, 2013 at 13:44
  • @atomman yes because I have a list of path and I can't rely on a separator (because I have no idea about the content of a path), so I kept the list Commented Jan 11, 2013 at 13:45
  • @fge the JSON should simply represent a Tree where each node contains an array of children and a count Commented Jan 11, 2013 at 13:47

3 Answers 3

2

I would create a tree structure using Nodes, then use XStream to serialize the structure. Examples below, hope this helps you out.

Convertion to Node structure

public static Node createNodes(Map<List<String>, Integer> map) {
    Map<String, Node> namemap = new HashMap<String, Node>();
    Node root = new Node();
    Node current;
    for (Entry<List<String>, Integer> path : map.entrySet()) {
        current = root;
        for (String nodename : path.getKey()) {
            Node p;
            if (!namemap.containsKey(nodename)){
                p = new Node(nodename, path.getValue());
                namemap.put(nodename, p);
            }else {
                p = namemap.get(nodename);
                p.addCost(path.getValue());
            }
            current.addChild(p);
            current = p;
        }

    }

    return root;
}

Serialization

public static String toXML(Node n) {
    XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
    xstream.alias("node", Node.class);
    return xstream.toXML(n);
}

Node Object

public class Node {

    private String name;
    private int count;
    private List<Node> children;

    public Node() {
        this(null, 0);
    }

    public Node(String name, int count) {
        this.name = name; 
        this.count = count;
        this.children = new ArrayList<Node>();
    }


    public void addChild(Node n) {
        for (Node nn : children) {
            if (nn.name.equals(n.name)) {
                return;
            }
        }
        this.children.add(n);
    }

    public void addCost(int i) {
        this.count += i;
    }
}

JSON output

{"node": {
  "count": 0,
  "children": [
    {
      "name": "c1",
      "count": 5,
      "children": [
        {
          "name": "c2",
          "count": 5,
          "children": [
            {
              "name": "c3",
              "count": 5,
              "children": [
                {
                  "name": "c4",
                  "count": 5,
                  "children": [
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "b1",
      "count": 10,
      "children": [
        {
          "name": "b2",
          "count": 6,
          "children": [
            {
              "name": "b3",
              "count": 3,
              "children": [
              ]
            }
          ]
        }
      ]
    },
    {
      "name": "a1",
      "count": 6,
      "children": [
        {
          "name": "a2",
          "count": 6,
          "children": [
            {
              "name": "a3",
              "count": 4,
              "children": [
              ]
            }
          ]
        }
      ]
    }
  ]
}}
Sign up to request clarification or add additional context in comments.

Comments

0

Me, personally, I would create a Node class that has children and my count value, then tell your JSON serializer how to serialize it properly for your needs.

Comments

0

I would change your Map to:

Map<String[], Integer>

if you want to stay with List, then use ArrayList and trim() it.

Then you have to decide if you use a HashMap, or if you really want a tree (TreeMap). In the later case you should create an Path object, with a field String[] or List<String>.
This Path object then must implement Comparable, which you habe to implement.

To perform a Serialisation (Json or others systems), you usually will writing out the key-value pairs. On reading back again you will build up your map or tree again by feeding in the (key, value) pairs.

It is not a good idea to have the tree structure in the json or otherwise serialized file. You will nearly never need that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.