3

I have a map of maps - Map> - collection.

I need to filter the map and get the outer map that has a given value for a given key of the inner map.

I tried some combinations, but it is not working.

How do I achieve this.

This is what I have tried

Map<String, Map<String, String>> originalMap = getOriginalMap();

String channelId = "channelIdVal";

Map<String, Map<String, String>> filteredMapForKey = originalMap.entrySet().stream()
    .collect(Collectors.toMap(Map.Entry::getKey,
        e -> e.getValue().entrySet().stream().filter(innerMap -> innerMap.getValue().equalsIgnoreCase(channelId)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));

Basically, I am expecting the filteredMapForKey to have a single entry whose inner map ( the value of the entry ) to contain a key whose value is channelId

How do I achieve that. The above code is returning the entire original map with same keys but empty inner maps except for the valid one. For the valid map, instead of returning the complete inner map, it is only return the map with the key and value of matching channel id

Thanks

Naman
  • 27,789
  • 26
  • 218
  • 353
adbdkb
  • 1,897
  • 6
  • 37
  • 66
  • *to contain a key whose value is channelId* ... remove `!` from `filter` condition. – Naman Jul 15 '19 at 15:09
  • @Naman - Thanks. Yeah - that was the typo that I realised right after posting the question. When I removed that, I get the results as added to the question. Basically _The above code is returning the entire original map with same keys but empty inner maps except for the valid one. For the valid map, instead of returning the complete inner map, it is only return the map with the key and value of matching channel id_ – adbdkb Jul 15 '19 at 15:11
  • That's because after filtering the inner entries you `collect` only those which satisfies the condition. – Naman Jul 15 '19 at 15:15

1 Answers1

1

Seems like there are two things to correct here:

  1. The filter logic to filter in entries instead of filtering them out.

  2. To filter only those outer entries for which inner map satisfies the condition stated.

You can achieve that as:

Map<String, Map<String, String>> filteredMapForKey = originalMap.entrySet()
        .stream()
        .filter(e -> e.getValue()
                .values()
                .stream()
                .anyMatch(innerMapVal -> innerMapVal.equalsIgnoreCase(channelId)))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

This filters all the outer map entries such that, the inner map for them has a value that is equal(ignoreCase) to the given channelId and then collects these entries into a similar Map as the input.

Naman
  • 27,789
  • 26
  • 218
  • 353
  • Thanks. This works. I still get confused when working with nested maps and streams on them. The explanation here also helps. – adbdkb Jul 15 '19 at 15:20
  • @adbdkb. Avoid using such maps in favor of concrete value types defined in the code. – Naman Jul 15 '19 at 15:22
  • Did not understand what you mean above. Can you explain? Thanks – adbdkb Jul 15 '19 at 15:24
  • @adbdkb What I meant was, you could have defined a class such as `class OriginalVal { String key; List innerValuesMapped;}` and used a `List` in the input instead of `Map>`. Ofc, there would have been another `class InnerVal { String innerKey; String innerVal;}` to complete such representation. – Naman Jul 15 '19 at 15:31