Please consider the follwing exemplifying code:
Function<Pair<String, String>, Integer> lengthOfKey
= p -> p.getKey().length();
Collector<Pair<String, String>, ?, Map<String, String>>
convertPairListToMap =
Collectors.toMap(
Pair<String, String>::getKey,
Pair<String, String>::getValue);
Function<Map<String, String>, Map<String, String>>
convertValueToUpperCase =
map -> map.entrySet().stream().collect(
Collectors.toMap(
Map.Entry::getValue,
e -> e.getValue().toUpperCase())
);
list.stream()
.collect(groupingBy(
lengthOfKey,
collectingAndThen(
convertPairListToMap,
convertValueToUpperCase
)))
.forEach((keyLength, map) -> {
// ...
});
I like that by writing
collectingAndThen(
convertPairListToMap,
convertValueToUpperCase
it is made explicit that the list of Pairs is converted to a Map and that the Values are modified. I don't want to do the uppercase conversion inside the Collector which converts the List to a Map because then this Collector would be doing more than just converting the List of Pairs to a Map as indicated by the name of the Collector. However, I don't like that in this solution the stream is collected two times - this is inefficient, isn't it? I'm therefore wondering if there is a solution to collect the stream only once, but still stating the converion to Map and the converting of the Values explictely. I searched the API for a method to combine two Collectors.toMap call, but couldn't find anything.
If you could simplify and share the problem you are attempting to solve with the implementation shared, you would most likely have a better and easier solution.
For what it seems like, the following should do what you are looking for (barring the
merging)The result of the following when executed for the sample
is the same as the code shared by you(when printed):