Java 中的深度嵌套哈希图
Deeply nested hashmaps in Java
我用这个例子来
Accessing Deeply nested HashMaps in Java
构建数据结构来存储节点名称和属性。
这是更新后的代码:
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;
}
}
以及我的用法示例:
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);
}
我不想为每个值都创建一个新对象,而是总是创建一个 new HashMap,我可以在其中存储节点属性。
我通过访问 JCR 数据存储中的节点并提取它们的值和属性来接收我的数据结构。这是我生成的数据结构在输出 yaml 文件中的样子:
我怎样才能更有效地做到这一点?
您特意让您使用任何键,但您使用的是字符串键,即使其中一个键是 "01"
,这表明它是一个数字。
我可以由此得出结论,键总是字符串吗?
在那种情况下,为什么不定义一个分隔符,比如斜杠,并使用普通的旧 TreeMap<String, V>
?然后你可以这样做:
m.put("de/content/01/fieldsets/0/fields", properties);
如果你想要 de/content/01
'tree' 中的所有内容,你可以这样做:
m.subMap("de/content/01/", "de/content/010");
以上将为您提供包含 de/content/01 中每个 child 的地图。 010
末尾的 0
有 'magic': 零是下一个字符,在斜线之后,在 ascii table.
如果您希望任何给定键映射到任意数量的值,您可以使用:
TreeMap<String, List<V>> map = new TreeMap<>();
把东西放进去:
map.computeIfAbsent(key, k -> new ArrayList<>()).add(elem);
并解决问题:
for (V value : map.getOrDefault(key, List.of())) {
// works even if key isn't in there (loops 0 times then)
}
使用递归解决问题
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;
}
我用这个例子来 Accessing Deeply nested HashMaps in Java 构建数据结构来存储节点名称和属性。
这是更新后的代码:
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;
}
}
以及我的用法示例:
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);
}
我不想为每个值都创建一个新对象,而是总是创建一个 new HashMap,我可以在其中存储节点属性。
我通过访问 JCR 数据存储中的节点并提取它们的值和属性来接收我的数据结构。这是我生成的数据结构在输出 yaml 文件中的样子:
我怎样才能更有效地做到这一点?
您特意让您使用任何键,但您使用的是字符串键,即使其中一个键是 "01"
,这表明它是一个数字。
我可以由此得出结论,键总是字符串吗?
在那种情况下,为什么不定义一个分隔符,比如斜杠,并使用普通的旧 TreeMap<String, V>
?然后你可以这样做:
m.put("de/content/01/fieldsets/0/fields", properties);
如果你想要 de/content/01
'tree' 中的所有内容,你可以这样做:
m.subMap("de/content/01/", "de/content/010");
以上将为您提供包含 de/content/01 中每个 child 的地图。 010
末尾的 0
有 'magic': 零是下一个字符,在斜线之后,在 ascii table.
如果您希望任何给定键映射到任意数量的值,您可以使用:
TreeMap<String, List<V>> map = new TreeMap<>();
把东西放进去:
map.computeIfAbsent(key, k -> new ArrayList<>()).add(elem);
并解决问题:
for (V value : map.getOrDefault(key, List.of())) {
// works even if key isn't in there (loops 0 times then)
}
使用递归解决问题
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;
}