Подтвердить что ты не робот

Как получить доступ к вложенным HashMaps в Java?

У меня есть HashMap на Java, содержимое которого (как вы, вероятно, знаете), может быть доступно

HashMap.get("keyname");

Если у вас есть HashMap внутри другого HashMap, то есть вложенного HashMap, как мне получить доступ к содержимому? Могу ли я сделать это следующим образом: inline:

HashMap.get("keyname").get("nestedkeyname");

Спасибо.

4b9b3361

Ответ 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;
    }
}