Reputation: 2161
I have a nested maps object like below
{12345={{"status":"200","outcome":"Success","message":"Account created"}}
{23121={{"status":"400","outcome":"Exception","message":"Invalid State value"}}
{43563={{"status":"200","outcome":"Success","message":"Account updated"}}
{72493={{"status":"400","outcome":"Exception","message":"Bad Request"}}
I need to transform this into Map<String, List<Map<String, Map<String, String>>>
where the key of outer map is value of the status ( 200 or 400 )
and the value is the list of original maps that have status = 200 or 400 or other valid values from the inner map.
So, the new structure would look like
{{200={[{12345={"status":"200","outcome":"Success","message":"Account created"}},
{43563={"status":"200","outcome":"Success","message":"Account updated"}}
]
},
{400={[{23121={"status":"400","outcome":"Exception","message":"Invalid State value"}},
{72493={"status":"400","outcome":"Exception","message":"Bad Request"}}
]
}
}
Ultimately, I need to generate a report based on the different stati.
This is what I have started with, but am stuck.
I want to loop through outer map, get the inner map, get the value of status key and add the map to a list based on status code value.
This is how I am doing it using loops
private static Map<String, List<Map<String, Map<String, String>>>> covertToReport(Map<String, Map<String, String>> originalMap) {
Map<String, List<Map<String, Map<String, String>>>> statusBasedListOfMaps = new TreeMap<>();
//loop through the map
//for each key, get the inner map
//get the status value for each inner map
List<Map<String, Map<String, String>>> accountsMapsList;
for (Entry<String, Map<String, String>> entry : originalMap.entrySet()) {
String accNum = entry.getKey();
Map<String, String> childMap = entry.getValue();
String stausVal = childMap.get("status");
accountsMapsList = statusBasedListOfMaps.get(stausVal) == null ? new ArrayList<>() : statusBasedListOfMaps.get(stausVal);
accountsMapsList.add((Map<String, Map<String, String>>) entry);
statusBasedListOfMaps.put(stausVal, accountsMapsList);
}
return statusBasedListOfMaps;
}
Of course, the below code doesn't compile, but that is what I am trying to get.
private static void covertToReport(Map<String, Map<String, String>> originalMap) {
Map<String, List<Map<String, Map<String, String>>>> statusBasedListOfMaps;
statusBasedListOfMaps = originalMap.entrySet()
.stream()
.filter(e -> e.getValue()
.values()
.stream()
.map(innerMap -> Collectors.toList())
.collect(Collectors.toMap(Map.Entry::getKey, Collectors.toList(e)));
Is this possible?
Upvotes: 1
Views: 1336
Reputation: 11032
You can just use Collectors.groupingBy()
with Collectors.mapping()
:
private static Map<String, List<Map<String, Map<String, String>>>> convertToReport(Map<String, Map<String, String>> originalMap) {
return originalMap.entrySet().stream()
.collect(Collectors.groupingBy(e -> e.getValue().get("status"),
Collectors.mapping(Map::ofEntries, Collectors.toList())));
}
You group by status
and then map the associated entry to an own map using Map.ofEntries()
. If you are using Java you can use this instead of Map::ofEntries
:
e -> new HashMap<>() {{ put(e.getKey(), e.getValue()); }}
The result will be this:
200=[
{12345={status=200, message=Account created, outcome=Success}},
{43563={status=200, message=Account created, outcome=Success}}
],
400=[
{72493={status=400, message=Invalid State value, outcome=Exception}},
{23121={status=400, message=Invalid State value, outcome=Exception}}
]
Upvotes: 2
Reputation: 131
Your function return a Map<String, List<Map<String, Map<String, String>>>>
, but your structure look like Map<String, Map<String, Map<String, String>>>
If what you really like is a Map<String, Map<String, Map<String, String>>>
here is the code:
Map<String, Map<String, Map<String, String>>> result= map.entrySet().stream().collect(Collectors.groupingBy(entry -> entry.getValue().get("status"), Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
Upvotes: 0