Как получить доступ к вложенным HashMaps в Java?
У меня есть HashMap на Java, содержимое которого (как вы, вероятно, знаете), может быть доступно
HashMap.get("keyname");
Если у вас есть HashMap внутри другого HashMap, то есть вложенного HashMap, как мне получить доступ к содержимому? Могу ли я сделать это следующим образом: inline:
HashMap.get("keyname").get("nestedkeyname");
Спасибо.
Ответы
Ответ 1
Вы можете сделать это так, как вы предполагали. Но ваш шаблон HashMap должен быть шаблонизирован:
Map<String, Map<String, String>> map =
new HashMap<String, Map<String, String>>();
В противном случае вам нужно сделать приведение к Map
после того, как вы извлечете вторую карту из первой.
Map map = new HashMap();
((Map)map.get( "keyname" )).get( "nestedkeyname" );
Ответ 2
Да.
Смотрите:
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"));
}
Ответ 3
Как говорили другие, вы можете это сделать, но вы должны определить карту с помощью дженериков:
Map<String, Map<String, String>> map = new HashMap<String, Map<String,String>>();
Однако, если вы просто слепо запускаете следующее:
map.get("keyname").get("nestedkeyname");
вы получите исключение с нулевым указателем всякий раз, когда ключевое имя не находится на карте и ваша программа выйдет из строя. Вы действительно должны добавить следующую проверку:
String valueFromMap = null;
if(map.containsKey("keyname")){
valueFromMap = map.get("keyname").get("nestedkeyname");
}
Ответ 4
Если вы планируете создавать HashMaps с переменной глубиной, используйте рекурсивную структуру данных.
Ниже приведена реализация, обеспечивающая образец интерфейса:
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;
}
}
и пример использования:
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());
}
}
Ответ 5
Да, если вы используете правильную подпись общего типа для внешней хэш-карты.
HashMap<String, HashMap<String, Foo>> hm = new HashMap<String, HashMap<String, Foobar>>();
// populate the map
hm.get("keyname").get("nestedkeyname");
Если вы не используете дженерики, вам нужно сделать трансляцию, чтобы преобразовать объект, полученный из внешней хэш-карты, в HashMap
(или по крайней мере a Map
), прежде чем вы сможете называть его get()
метод. Но вы должны использовать дженерики, -)
Ответ 6
Я предпочитаю создавать пользовательскую карту, которая расширяет 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;
}
}
}
Теперь вы можете использовать его так:
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);
Ответ 7
Я пришел на эту страницу StackOverflow, чтобы узнать что-то ala valueForKeyPath
, известное из objc. Я также пришел к другому сообщению - "Key-Value Coding" для Java, но в итоге я написал свой собственный.
Я все еще ищу лучшее решение, чем PropertyUtils.getProperty
в apache beanutils
.
Использование
Map<String, Object> json = ...
public String getOptionalFirstName() {
return MyCode.getString(json, "contact", "firstName");
}
Реализация
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;
}
Ответ 8
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"));
} }
Ответ 9
Я попал в это обсуждение, пытаясь выяснить, как получить значение из вложенной карты неизвестной глубины, и это помогло мне найти следующее решение моей проблемы. Для оригинального вопроса это излишне, но, возможно, это будет полезно для кого-то, кто оказывается в ситуации, когда у вас меньше знаний о поиске карты.
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;
}
}