HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

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

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mapmethoditerateoptimizelistobjectstringover

Problem

I have a Map> multiFieldMap and I need to iterate over its value set and add the value to multiFieldsList:

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


Can this method be simplified further?

Solution

You can accomplish this using Java 8 streams.

public List fetchMultiFieldsList() {
    return multiFieldMap.entrySet().stream()
      .flatMap(e -> {
          String entityName = e.getKey();
          List 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 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.

Code Snippets

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());
}
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());
}

Context

StackExchange Code Review Q#88102, answer score: 6

Revisions (0)

No revisions yet.