# Optimize method to iterate to over Map<String, List<Object>>

I have a Map<String, List<Object>> multiFieldMap and I need to iterate over its value set and add the value to multiFieldsList:

public List<Object> fetchMultiFieldsList() {
List<Object> multiFieldsList = new ArrayList<>();
for (Entry<String, List<Object>> entry : multiFieldMap.entrySet()) {
String entityName = entry.getKey();
List<Object> ids = entry.getValue();
for (Object id : ids) {
Object entity = queryService.query(entityName, queryService.property("id").eq(id));
}
}
return multiFieldsList;
}


Can this method be simplified further?

You can accomplish this using Java 8 streams.

public List<Object> fetchMultiFieldsList() {
return multiFieldMap.entrySet().stream()
.flatMap(e -> {
String entityName = e.getKey();
List<Object> ids = e.getValue();
return ids.stream()
.map(id -> queryService.query(entityName, queryService.property("id").eq(id)));
}).collect(Collectors.toList());
}


I think the code itself is relatively self-explanatory. The important bit is the usage of flatMap instead of map for the first mapping operation so that the resulting streams are concatenated, ending up with a flat list of objects rather than a list of lists.

It is unfortunate that Java does not support destructuring assignment, which would allow the first lambda expression to be a single expression of the form (k, v) -> ..., but it does not, so I've left the statements in for clarity.

If you are willing to omit the inner declarations, the above code can be simplified further.

public List<Object> fetchMultiFieldsList() {
return multiFieldMap.entrySet().stream()
.flatMap(e -> e.getValue().stream()
.map(id -> queryService.query(e.getKey(), queryService.property("id").eq(id)))
).collect(Collectors.toList());
}


Whichever one you prefer is a matter of personal preference. The former has more descriptive variable names, while the latter is simpler and more functional.

You could replace the map with a multimap. Using Google's Guava Multimap, you don't need the nested loop / flatMap():

private Multimap<String, Object> multiFieldMap = ArrayListMultimap.create();

public List<Object> fetchMultiFieldsList() {
return multiFieldMap.entries().stream()
.map(e -> queryService.query(e.getKey(),
queryService.property("id").eq(e.getValue())))
.collect(Collectors.toList());
}