Search code examples
javajava-8hashmapjava-streamcollectors

Could you help me to merge values of several maps?


I'm trying to do the following modification:

final Map<String, List<Map<String, String>>> scopes = scopeService.fetchAndCacheScopesDetails();
final Map<String, Map<String, String>> scopesResponse = scopes.entrySet().stream().collect
        (Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
                .stream().collect(Collectors.toMap(s -> (String) s.get(SCOPE_NM), s -> (String) s.get(SCOPE_ID))))
        );

But I face "Duplicate key" error, so I'd like to change scopeResponses to Map<String, Map<String, List<String>>>

Could you tell me how to merge values s -> (String) s.get(SCOPE_ID) into a List or Set in this situation?


Solution

  • You need to create a Set for the value of the inner Map, and supply a merge function:

    final Map<String, Map<String, Set<String>>> scopesResponse = scopes.entrySet().stream().collect
        (Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
                .stream().collect(Collectors.toMap(s -> s.get(SCOPE_NM),
                                                   s -> {Set<String> set= new HashSet<>(); set.add(s.get(SCOPE_ID)); return set;},
                                                   (s1,s2)->{s1.addAll(s2);return s1;}))));
    

    Or, you can construct the inner Map with groupingBy:

    final Map<String, Map<String, Set<String>>> scopesResponse2 = scopes.entrySet().stream().collect
        (Collectors.toMap(Map.Entry::getKey, e -> e.getValue()
                .stream().collect(Collectors.groupingBy(s -> s.get(SCOPE_NM),
                                                   Collectors.mapping(s -> s.get(SCOPE_ID),Collectors.toSet())))));