Lubelmont
Lubelmont

Reputation: 7

Get a String from a Map inside Map Java 8

What do you think is the best way to find a value in a map inside another map.

    Map <String, String> map1 = new HashMap<>();

    map1.put("map1|1", "1.1");
    map1.put("map1|2", "1.2");
    map1.put("map1|3", "1.3");
    map1.put("map1|4", "1.4");

    Map <String, String> map2 = new HashMap<>();

    map2.put("map2|1", "2.1");
    map2.put("map2|2", "2.2");
    map2.put("map2|3", "2.3");
    map2.put("map2|4", "2.4");


    Map<String, Map> mapOfMaps = new HashMap<>();

    mapOfMaps.put("MAP|map1", map1);
    mapOfMaps.put("MAP|map2", map2);

Now if I need the value of "MAP|map2" (inside mapOfMaps) and "map2|3" (inside map2) will be "2.3"

I tried to do something like:

System.out.println("x="+getValue(mapOfMaps,"MAP|map2", "map2|4"));

public static String getValue (Map<String, Map> map,String mapfind, String val) {

     Map<Object, Object> mp = map.entrySet().stream()
                .filter(x -> x.getKey().equals(mapfind))
                .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));

     System.out.println("--------"+mp);

     return (String) mp.get(val);
 }

but the result is:

--------{MAP|map2={map2|1=2.1, map2|4=2.4, map2|2=2.2, map2|3=2.3}}
x=null

Can you help me with some ideas?

Upvotes: 0

Views: 2438

Answers (3)

Ashishkumar Singh
Ashishkumar Singh

Reputation: 3600

I think the easiest way to get your desired output would be to use map.get(mapfind).get(val). But if you want to achieve it using your existing code, you could call values() on the collected map and call filter to get a second level filter. Below is the code snippet of your modified method

public static String getValue(Map<String, Map> map, String mapfind, String val) {
    Map mp = map.entrySet().stream().filter(x -> x.getKey().equals(mapfind))
            .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()))

            .values().stream().filter(y -> y.containsKey(val)).findAny().orElse(null);

    System.out.println("--------" + mp);
    if (mp == null)
        return "";
    return (String) mp.get(val);
}

Upvotes: 0

Tom Drake
Tom Drake

Reputation: 537

public static String getValue (Map<String, Map> map,String mapfind, String val) {
    Map childMap = map.get(mapfind);
    if (childMap == null) {
        return null;
    }
    return childMap.containsKey(val) ? childMap.get(val).toString() : null;
}

Upvotes: -1

LuCio
LuCio

Reputation: 5173

Instead of declaring mapOfMaps by its raw type it should be defined as

Map<String, Map<String, String>> mapOfMaps = new HashMap<>();

The corresponding getValue method would look like this:

  public static String getValue(Map<String, Map<String, String>> mapOfMaps, String mapfind, String val) {
    Map<String, String> innerMap = mapOfMaps.get(mapfind);
    return innerMap != null ?
      innerMap.get(val) :
      null;
  }

Using Optional we can write it as follows:

  public static String getValue(Map<String, Map<String, String>> mapOfMaps, String mapfind, String val) {
    return Optional.ofNullable(mapOfMaps.get(mapfind))
      .map(m -> m.get(val))
      .orElse(null);
  }

If we kept mapOfMaps declared by its raw type we would get in the first version of getValue a type safety warning about an unchecked conversion and in the second version we would need explicitly cast the result to String. Since we use mapOfMaps only to map String keys to String values we should declare it accordingly.


Further reading: What is a raw type and why shouldn't we use it?

Upvotes: 3

Related Questions