Search code examples
javahashmapjava-streamrefactoringcollectors

Java-Stream - Transforming List to a nested Map


How can I simplify the following code? Can it be written as a single stream-statement?

Clarification: multiple id of branch can correspond to the same appName

My code:

Map<String, Map<Long, BranchSession>> sessions = new HashMap<>();

Map<String, Map<Long, List<Branch>>> map = branches.stream()
   .collect(
      Collectors.groupingBy(
         Branch::getAppName,
         Collectors.groupingBy(Branch::getId)
   ));

map.forEach((key, value) -> {
    Map<Long, BranchSession> bs = new HashMap<>();
    value.keySet().forEach(bId -> {
    List<Branch> list = value.get(bId);
    if (list.size() > 0)
       bs.put(bId, new BranchSession(value.get(bId).get(0)));
    });
    sessions.put(key, bs);
});

Solution

  • I'm assuming that there could be multiple id that correspond to the same appName (otherwise creating such a nested map is unnecessary, if each appName corresponds to a single unique id you can create two separate maps: branchSession by id Map<Long, BranchSession> and branchSession by name Map<String, BranchSession> which would be more convenient).

    If my assumption is correct, you can apply collector toMap as the downstream of groupingBy:

    Map<String, Map<Long, BranchSession>> branchSessionByIdAndByName = branches.stream()
        .collect(Collectors.groupingBy(
            Branch::getAppName,
                Collectors.toMap(
                    Branch::getId,
                    branch -> new BranchSession(branch.getId())
                )
        ));
    

    A link to Online Demo