Belphegor21
Belphegor21

Reputation: 484

Transform simple map to Map of list of map

I have a Map<String, List<String>> and I need to transform it to Map<String, List<Map<String, String>>> using lambda. Using a normal for loop this problem is trivial but I want to tackle it using java8 lambdas.

The categoryToSubCat is of type <String, List<String>>.

Using for loops this is the transformation:

final Map < String, List < Map < String, String >>> transformedMap = new HashMap < > ();
for (Map.Entry < String, List < String >> entry: categoryToSubCat.entrySet()) {
    final List < Map < String, String >> subCats = new ArrayList < > ();
    for (String subCat: entry.getValue()) {
        final Map < String, String > data = new HashMap < > ();
        data.put("text", subCat);
        data.put("value", subCat);
        subCats.add(data);
    }
    transformedMap.put(entry.getKey(), subCats);
}

The initial map contains data like:

{
  "CAT1": [
    "CAT1-A",
    "CAT1-B"
  ],
  "CAT2": [
    "CAT2-A",
    "CAT2-B",
    "CAT2-C"
  ]
}

After the transformation it should become something like

{
  "CAT1": [
    {
      "text": "CAT1-A",
      "value": "CAT1-A"
    },
    {
      "text": "CAT1-B",
      "value": "CAT1-B"
    }
  ],
  "CAT2": [
    {
      "text": "CAT2-A",
      "value": "CAT2-A"
    },
    {
      "text": "CAT2-B",
      "value": "CAT2-B"
    },
    {
      "text": "CAT2-C",
      "value": "CAT2-C"
    }
  ]
}

This does not seem like a problem which cannot be solved using lambdas but I'm just able to get how to do about it.

Please suggest a better approach than the for loop.

Upvotes: 1

Views: 121

Answers (2)

Feilong Sun
Feilong Sun

Reputation: 1

Here is a lambda version code.

Map<String, List<Map<String, String>>> transformedMap = categoryToSubCat.keySet()
                .stream()
                .collect(Collectors.toMap(
                        //keyMapper
                        key -> key,
                        //valueMapper
                        key -> categoryToSubCat.get(key).stream().map(listStr -> {
                                    Map<String, String> map= new HashMap<>();
                                    map.put("text", listStr);
                                    map.put("value", listStr);
                                    return map;
                                }
                        ).collect(Collectors.toList())
                ));

or

Map<String, List<Map<String, String>>> transformedMap = categoryToSubCat.entrySet()
                .stream()
                .collect(Collectors.toMap(
                        //keyMapper
                        Map.Entry::getKey,
                        //valueMapper
                        entrySet -> entrySet.getValue().stream().map(listStr -> {
                                    Map<String, String> map= new HashMap<>();
                                    map.put("text", listStr);
                                    map.put("value", listStr);
                                    return map;
                                }
                        ).collect(Collectors.toList())
                ));

Upvotes: 0

Naman
Naman

Reputation: 31878

Though an ideal suggestion would be to not use such a data structure, yet if you were to transform the given input, you could try something like:

Map<String, List<Map<String, String>>> transformedMap = categoryToSubCat.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey,
                entry -> entry.getValue()
                        .stream()
                        .map(subCat -> Map.of("text", subCat, "value", subCat))
                        .collect(Collectors.toList()), (a, b) -> b));

Upvotes: 1

Related Questions