简体   繁体   English

Java 中深度嵌套的 hashmap

[英]Deeply nested hashmaps in Java

I have used this example to Accessing Deeply nested HashMaps in Java build the data structure to store node names and properties.我已使用此示例在 Java 中访问深度嵌套的 HashMap构建数据结构以存储节点名称和属性。

Here is the updated code:这是更新后的代码:

class NestedMap {

private final HashMap<String, NestedMap> child;

private Map<String, Object> value = new HashMap<>();

public NestedMap() {
    child = new HashMap<>();
    setValue(null);
}

public boolean hasChild(String k) {
    return this.child.containsKey(k);
}

public NestedMap getChild(String k) {
    return this.child.get(k);
}

public void makeChild(String k) {
    this.child.put(k, new NestedMap());
}

public Map<String, Object> getValue() {
    return value;
}

public void setValue(Map<String, Object> value) {
    this.value = value;
}

} }

And my usage example:我的用法示例:

    class NestedMapIllustration {
        public static void main(String[] args) {

        NestedMap m = new NestedMap();

        m.makeChild("de");
        m.getChild("de").makeChild("content");
        m.getChild("de").getChild("content").makeChild("00");
        m.getChild("de").getChild("content").makeChild("0");
        m.getChild("de").getChild("content").makeChild("1");
        m.getChild("de").getChild("content").makeChild("01");
        m.getChild("de").getChild("content").getChild("01").makeChild("fieldsets");
        m.getChild("de").getChild("content").getChild("01").getChild("fieldsets").makeChild("0");
        m.getChild("de").getChild("content").getChild("01").getChild("fieldsets").getChild("0").makeChild("fields");
        m.getChild("de").getChild("content").getChild("01").getChild("fieldsets").getChild("0").getChild("fields").makeChild("0");
        Map<String, Object> properties = new HashMap<>();
        properties.put("key", "value");
        properties.put("key2", "value");
        m.getChild("de").getChild("content").getChild("01").getChild("fieldsets").getChild("0").getChild("fields").setValue(properties);
}

Instead of creating a new object each value I would like to always create a new HashMap where I can store the node properties.我不想为每个值创建一个新对象,而是始终创建一个新的 HashMap ,我可以在其中存储节点属性。

I receive my data structure by visiting nodes in the JCR datastore and extracting their values and properties.我通过访问 JCR 数据存储中的节点并提取它们的值和属性来接收我的数据结构。 This is how my resulting data structure should look in the output yaml file:这是我生成的数据结构在输出 yaml 文件中的样子:

在此处输入图像描述

How can I do that more efficiently?我怎样才能更有效地做到这一点?

You've gone out of your way to let you use any key, but you're using string keys, even though one of the keys is "01" which suggests it's a number instead.你特意让你使用任何键,但你使用的是字符串键,即使其中一个键是"01" ,这表明它是一个数字。

Can I conclude from this that keys are always strings?我可以由此得出结论,键总是字符串吗?

In that case, why not define a separator, say, the slash, and use a plain old TreeMap<String, V> ?在那种情况下,为什么不定义一个分隔符,比如斜杠,并使用普通的旧TreeMap<String, V> Then you can do:然后你可以这样做:

m.put("de/content/01/fieldsets/0/fields", properties);

If you want everything in the de/content/01 'tree', you can do:如果你想要de/content/01 '树' 中的所有内容,你可以这样做:

m.subMap("de/content/01/", "de/content/010");

The above will give you a map containing every child of de/content/01.以上将为您提供包含 de/content/01 的每个子项的地图。 The 0 at the end of the 010 there is 'magic': Zero is the next character, after slash, in the ascii table. 010末尾的0具有“魔力”:零是 ascii 表中斜线后的下一个字符。

If you want any given key to map to any number of values, you can use:如果您希望任何给定的键映射到任意数量的值,您可以使用:

TreeMap<String, List<V>> map = new TreeMap<>();

to put things in:把东西放进去:

map.computeIfAbsent(key, k -> new ArrayList<>()).add(elem);

and to get things out:并把事情弄清楚:

for (V value : map.getOrDefault(key, List.of())) {
    // works even if key isn't in there (loops 0 times then)
}

Solution to the problem using recursion使用递归解决问题

public HashMap<String,Object> nestedMap(Node node) {

           HashMap<String, Object> map = new LinkedHashMap<>();

           PropertyIterator pi;
            try {
                pi = node.getProperties();
                //Get properties for the root node
                   while(pi.hasNext())
                    {
                       Property p = pi.nextProperty();
                       String name = p.getName();
                       String val = p.getString();

                       map.put(name,val);

                    }//end of while for properties of root node
            } catch (RepositoryException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


           Iterable<Node> children;
            try {
                children = NodeUtil.getNodes(node);
                for (Node child : children) {

                    if (!child.getPrimaryNodeType().getName().contains("mgnl:page")) {  
                      map.put (child.getName(), nestedMap(child));

                   }//end of checking if PrimaryNodeType is of type mgnl:page
                }

            } catch (RepositoryException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return map;
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM