2

I have a map, Map<String, Map<String, String>> myMap = new HashMap<>(); that I would like to remap to get it's values, so that I get as a result Map<String, String>.

Is it possible to do the mapping using stream API?

I have solved the problem using a for loop but I'm interested if that could be done using streams.

My solution:

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

    myMap.forEach((k, v) -> {
        result.putAll(v);
    });

What I want is to get all the values from myMap and put them in a new Map.

3
  • So you're just throwing away the keys of the initial map , and flattening the inner maps. What about uniqueness of the keys (are you ok with overriding values)? Commented Oct 31, 2022 at 15:13
  • @AlexanderIvanchenko yes that is what I am trying to do. The keys are all unique. Commented Oct 31, 2022 at 15:14
  • 1
    In short, if you want to address the problem using a stream, you need to flatten the entries of the nested maps. E.g. Map<String, String> result = myMap.entrySet().stream() .flatMap(entry -> entry.getValue().entrySet().stream()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue )); Commented Oct 31, 2022 at 15:37

2 Answers 2

1

If you are certain there are no duplicate keys, you can do it like this.

Map<String, String> res = myMap.values()
            .stream()
            .flatMap(value -> value.entrySet().stream())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);

If there may be duplicate keys between the inner maps, you will have to introduce merge function to resolve conflicts. Simple resolution keeping the value of the second encountered entry may look like this:

Map<String, String> res = myMap.values()
            .stream()
            .flatMap(value -> value.entrySet().stream())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2));

Basically, stream the values, which are Maps, flatten them to a stream of entries and collect the entries in a new Map.

Sign up to request clarification or add additional context in comments.

Comments

1

You need to flatten the entries of the nested maps which can be done using either flatMap() or mapMulty().

And then apply collect() with the minimalistic two-args flavor of Collector toMap() passed as an argument. It would be sufficient since you don't expect duplicates.

Here's an example using flatMap():

Map<String, Map<String, String>> myMap = new HashMap<>();
        
Map<String, String> res = myMap.entrySet().stream()         // stream of maps
    .flatMap(entry -> entry.getValue().entrySet().stream()) // stream of map entries
    .collect(Collectors.toMap(
        Map.Entry::getKey,  // key mapper
        Map.Entry::getValue // value mapper
    ));

Example with Java 16 mapMulti() used for flattening the data:

Map<String, Map<String, String>> myMap = new HashMap<>();
        
Map<String, String> res = myMap.entrySet().stream()   // stream of maps
    .<Map.Entry<String, String>>mapMulti((entry, consumer) -> 
        entry.getValue().entrySet().forEach(consumer) // stream of map entries
    )
    .collect(Collectors.toMap(
        Map.Entry::getKey,  // key mapper
        Map.Entry::getValue // value mapper
    ));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.