如何在 Java 中访问嵌套的 HashMap?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2774608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I access nested HashMaps in Java?
提问by Mridang Agarwalla
I have a HashMap in Java, the contents of which (as you all probably know) can be accessed by
我有一个 Java 中的 HashMap,其内容(你们可能都知道)可以通过以下方式访问
HashMap.get("keyname");
If a have a HashMap inside another HashMap i.e. a nested HashMap, how would i access the contents? Can i do this like this, inline:
如果在另一个 HashMap 中有一个 HashMap,即嵌套的 HashMap,我将如何访问内容?我可以这样做吗,内联:
HashMap.get("keyname").get("nestedkeyname");
Thank you.
谢谢你。
采纳答案by tangens
You can do it like you assumed. But your HashMap has to be templated:
你可以像你想象的那样做。但是你的 HashMap 必须被模板化:
Map<String, Map<String, String>> map =
new HashMap<String, Map<String, String>>();
Otherwise you have to do a cast to Map
after you retrieve the second map from the first.
否则,您必须在Map
从第一张地图检索第二张地图后进行强制转换。
Map map = new HashMap();
((Map)map.get( "keyname" )).get( "nestedkeyname" );
回答by David Z
Yes, if you use the proper generic type signature for the outer hashmap.
是的,如果您对外部哈希映射使用正确的泛型类型签名。
HashMap<String, HashMap<String, Foo>> hm = new HashMap<String, HashMap<String, Foobar>>();
// populate the map
hm.get("keyname").get("nestedkeyname");
If you're not using generics, you'd have to do a cast to convert the object retrieved from the outer hash map to a HashMap
(or at least a Map
) before you could call its get()
method. But you should be using generics ;-)
如果您不使用泛型,则HashMap
在Map
调用其get()
方法之前,您必须进行强制转换,将从外部哈希映射检索到的对象转换为 a (或至少 a )。但是你应该使用泛型;-)
回答by Benjamin Borden
Yes.
是的。
See:
看:
public static void main(String args[]) {
HashMap<String, HashMap<String, Object>> map = new HashMap<String, HashMap<String,Object>>();
map.put("key", new HashMap<String, Object>());
map.get("key").put("key2", "val2");
System.out.println(map.get("key").get("key2"));
}
回答by Jay Askren
As others have said you can do this but you should define the map with generics like so:
正如其他人所说,您可以这样做,但您应该使用泛型定义地图,如下所示:
Map<String, Map<String, String>> map = new HashMap<String, Map<String,String>>();
However, if you just blindly run the following:
但是,如果您只是盲目地运行以下内容:
map.get("keyname").get("nestedkeyname");
you will get a null pointer exception whenever keyname is not in the map and your program will crash. You really should add the following check:
每当键名不在映射中时,您将收到空指针异常,并且您的程序将崩溃。您确实应该添加以下检查:
String valueFromMap = null;
if(map.containsKey("keyname")){
valueFromMap = map.get("keyname").get("nestedkeyname");
}
回答by neoneye
I came to this StackOverflow page looking for a something ala valueForKeyPath
known from objc. I also came by another post - "Key-Value Coding" for Java, but ended up writing my own.
我来到这个 StackOverflow 页面是为了寻找valueForKeyPath
objc 中已知的东西。我还看到了另一篇文章 - Java 的“键值编码”,但最终还是写了我自己的。
I'm still looking for at better solution than PropertyUtils.getProperty
in apache's beanutils
library.
我仍在寻找比PropertyUtils.getProperty
apachebeanutils
库更好的解决方案。
Usage
用法
Map<String, Object> json = ...
public String getOptionalFirstName() {
return MyCode.getString(json, "contact", "firstName");
}
Implementation
执行
public static String getString(Object object, String key0, String key1) {
if (key0 == null) {
return null;
}
if (key1 == null) {
return null;
}
if (object instanceof Map == false) {
return null;
}
@SuppressWarnings("unchecked")
Map<Object, Object> map = (Map<Object, Object>)object;
Object object1 = map.get(key0);
if (object1 instanceof Map == false) {
return null;
}
@SuppressWarnings("unchecked")
Map<Object, Object> map1 = (Map<Object, Object>)object1;
Object valueObject = map1.get(key1);
if (valueObject instanceof String == false) {
return null;
}
return (String)valueObject;
}
回答by Matt
If you plan on constructing HashMaps with variable depth, use a recursive data structure.
如果您计划构建具有可变深度的HashMap ,请使用递归数据结构。
Below is an implementation providing a sample interface:
下面是一个提供示例界面的实现:
class NestedMap<K, V> {
private final HashMap<K, NestedMap> child;
private V value;
public NestedMap() {
child = new HashMap<>();
value = null;
}
public boolean hasChild(K k) {
return this.child.containsKey(k);
}
public NestedMap<K, V> getChild(K k) {
return this.child.get(k);
}
public void makeChild(K k) {
this.child.put(k, new NestedMap());
}
public V getValue() {
return value;
}
public void setValue(V v) {
value = v;
}
}
and example usage:
和示例用法:
class NestedMapIllustration {
public static void main(String[] args) {
NestedMap<Character, String> m = new NestedMap<>();
m.makeChild('f');
m.getChild('f').makeChild('o');
m.getChild('f').getChild('o').makeChild('o');
m.getChild('f').getChild('o').getChild('o').setValue("bar");
System.out.println(
"nested element at 'f' -> 'o' -> 'o' is " +
m.getChild('f').getChild('o').getChild('o').getValue());
}
}
回答by Cody Wagner
I prefer creating a custom map that extends HashMap. Then just override get() to add extra logic so that if the map doesnt contain your key. It will a create a new instance of the nested map, add it, then return it.
我更喜欢创建一个扩展 HashMap 的自定义映射。然后只需覆盖 get() 以添加额外的逻辑,以便地图不包含您的密钥。它将创建嵌套地图的新实例,添加它,然后返回它。
public class KMap<K, V> extends HashMap<K, V> {
public KMap() {
super();
}
@Override
public V get(Object key) {
if (this.containsKey(key)) {
return super.get(key);
} else {
Map<K, V> value = new KMap<K, V>();
super.put((K)key, (V)value);
return (V)value;
}
}
}
Now you can use it like so:
现在你可以像这样使用它:
Map<Integer, Map<Integer, Map<String, Object>>> nestedMap = new KMap<Integer, Map<Integer, Map<String, Object>>>();
Map<String, Object> map = (Map<String, Object>) nestedMap.get(1).get(2);
Object obj= new Object();
map.put(someKey, obj);
回答by Adam DeWitt
I hit this discussion while trying to figure out how to get a value from a nested map of unknown depth and it helped me come up with the following solution to my problem. It is overkill for the original question but maybe it will be helpful to someone that finds themselves in a situation where you have less knowledge about the map being searched.
我在试图弄清楚如何从未知深度的嵌套地图中获取值时遇到了这个讨论,它帮助我想出了以下解决我的问题的方法。对于原始问题来说,这太过分了,但对于发现自己处于对所搜索地图知之甚少的情况下的人来说,这可能会有所帮助。
private static Object pullNestedVal(
Map<Object, Object> vmap,
Object ... keys) {
if ((keys.length == 0) || (vmap.size() == 0)) {
return null;
} else if (keys.length == 1) {
return vmap.get(keys[0]);
}
Object stageObj = vmap.get(keys[0]);
if (stageObj instanceof Map) {
Map<Object, Object> smap = (Map<Object, Object>) stageObj;
Object[] skeys = Arrays.copyOfRange(keys, 1, keys.length);
return pullNestedVal(smap, skeys);
} else {
return null;
}
}
回答by user12193365
import java.util.*;
public class MyFirstJava {
public static void main(String[] args)
{
Animal dog = new Animal();
dog.Info("Dog","Breezi","Lab","Chicken liver");
dog.Getname();
Animal dog2= new Animal();
dog2.Info("Dog", "pumpkin", "POM", "Pedigree");
dog2.Getname();
HashMap<String, HashMap<String, Object>> dogs = new HashMap<>();
dogs.put("dog1", new HashMap<>() {{put("Name",dog.name);
put("Food",dog.food);put("Age",3);}});
dogs.put("dog2", new HashMap<>() {{put("Name",dog2.name);
put("Food",dog2.food);put("Age",6);}});
//dogs.get("dog1");
System.out.print(dogs + "\n");
System.out.print(dogs.get("dog1").get("Age"));
} }
} }
回答by Holger L
You can get the nested value by repeating .get()
, but with deeply nested maps you have to do a lot of casting into Map
. An easier way is to use a generic method for getting a nested value.
您可以通过重复获得嵌套值.get()
,但是对于深度嵌套的映射,您必须进行大量的转换为Map
. 一种更简单的方法是使用通用方法来获取嵌套值。
Implementation
执行
public static <T> T getNestedValue(Map map, String... keys) {
Object value = map;
for (String key : keys) {
value = ((Map) value).get(key);
}
return (T) value;
}
Usage
用法
// Map contents with string and even a list:
{
"data": {
"vehicles": {
"list": [
{
"registration": {
"owner": {
"id": "3643619"
}
}
}
]
}
}
}
List<Map> list = getNestedValue(mapContents, "data", "vehicles", "list");
Map first = list.get(0);
String id = getNestedValue(first, "registration", "owner", "id");