I currently have some data in the form of a nested map like the following:
Map<String, Map<String, List<Integer>>> data = // intializing the Map
// data = {group1={grades=[a,b,c], age=[x,y,z]}, group={....}} and so on
What I want to do is essentially remove grades and then reverse the map, so it would look something like:
{x={group1}, y={group1, group3}, z={group2}, someAge={some list of groupN}}
I appreciate that the data may not make sense without context, but the problem remains the same. As it stands, I have a 3-nested for loops, but there must be a better way, since that would be very inefficient with a large dataset:
Map <Integer, List<String>> someMap = new HashMap<>();
for (var entry : data.entrySet()) {
for (var info : entry.getValue().entrySet()) {
if (info.getKey().equals("age")) {
List ages = info.getValue();
for (var age : ages) {
// if age not in someMap, add age as key // e.g add x so someMap={x={},y={}}
someMap.get(age).add(entry.getKey()) //e.g {x={entry key},y={}}
}
}
}
}
Is there some kind of pre-processing I can do to remove grades which would cut the 2nd for loop in half at least, and remove the need to check if the key is 'age' each iteration.
CodePudding user response:
You should use Map.get(), instead of iteration to find the value of a key.
for(var entry : data.entrySet()) {
var ages = entry.getValue().get("age");
if (ages == null) {
//key does not exist
//initialize or whatever you need
} else {
//key exists
//operate on list
}
}
CodePudding user response:
You don't need the second nested for
-loop where you're iterating over the entry sets of the inner Map searching for the key "age"
. Instead, you can retrieve a value that corresponds to this key from each inner Map.
That's how your logic can be implemented using Java 8 methods Map.computeIfAbsent()
and Map.forEach()
.
As a precaution against the case when the key "age"
is not present in the inner Map you can use Map.getOrDefault()
Map<String, Map<String, List<Integer>>> data = // {group1={grades=[a,b,c], age=[x,y,z]}, group={....}} and so on
Map<Integer, List<String>> groupsByAge = new HashMap<>();
data.forEach((group, nestedMap) -> {
nestedMap.getOrDefault("age", List.of()).forEach(age ->
groupsByAge.computeIfAbsent(age, k -> new ArrayList<>()).add(group)
);
});