Issue
How can I write the logic to obtain a Map<String, Map<String, String>>
using streams?
Here is the code I have tried :
public Map<String, Map<String, String>> getData(Set<String> Ids) {
List<Events> events = repository.findAllByIdIn(Ids);
int i = 0;
return events.stream()
.sorted(Comparator.comparing(Events::getMajor).thenComparing(Events::getMinor))
.collect(Collectors.groupingBy(Events::getId,
//Error-Cannot resolve method 'getMajor()'
Collectors.mapping(cae -> cae.getMajor() + "." + cae.getMinor(),
cae.getDates().get(i).getEndDate() != null ? "Predicted" : "Not Predicted"),
Collectors.toMap())));//Error-Cannot resolve method 'toMap()'
}
So how do I loop through a map inside another map?
Solution
Collector toMap()
contrary to collectors toList()
and toSet()
isn't parameterless, you need to provide information how a key and a value should be extracted from a single stream element.
Collectors.toMap()
expects at least two functions: keyMapper
and valueMapper
. In case if there could be duplicates, you need to use the flavor of toMap
which takes a mergeFunction
as a third argument to resolve the values that collide on the same key.
So you need to place toMap()
as a second argument (downstream collector) into the groupingBy
. That will be a syntactically correct structure of the collectors and functions:
Collectors.groupingBy(classifier, Collectors.toMap(keyMapper, valueMapper))
And that how the code might look like:
return events.stream()
.sorted(Comparator.comparing(Events::getMajor)
.thenComparing(Events::getMinor))
.collect(Collectors.groupingBy(Events::getId,
Collectors.toMap(cae -> cae.getMajor() + "." + cae.getMinor(),
cae -> cae.getDates().get(i).getEndDate() != null ?
"Predicted" : "Not Predicted")));
Note, Collectors.mapping()
isn't meant to produce a Map
but to transform the elements of the stream, you can think of it as an analog of the map()
operation that is done not is the middle of the stream pipeline, but during the process of collecting the data.
And if I understood your logic correctly, there's no need to apply mapping()
here.
Answered By - Alexander Ivanchenko
Answer Checked By - Candace Johnson (JavaFixing Volunteer)