I am trying to learn to work with streams and collectors, I know how to do it with multiple for loops but I want to become a more efficient programmer.
Each project has a map committedHoursPerDay, where the key is the employee and the value is the amount of hours expressed in Integer. I want to loop through all project's committedHoursPerDay maps and filter the maps where the committedHoursPerDay is more than 7(fulltime), and add each of the Employee who works fulltime to the set.
The code that i have written so far is this:
public Set<Employee> getFulltimeEmployees() {
// TODO
Map<Employee,Integer> fulltimeEmployees = projects.stream().filter(p -> p.getCommittedHoursPerDay().entrySet()
.stream()
.filter(map -> map.getValue() >= 8)
.collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue())));
return fulltimeEmployees.keySet();
}
however the filter recognizes the map because I can access the key and values, but in the .collect(Collectors.toMap()) it doesnt recognize the map and only sees it as a lambda argument
There is one to many notion here. You can first flatten the maps using flatMap
and then apply filter
to the map entries.
Map<Employee,Integer> fulltimeEmployees = projects.stream()
.flatMap(p -> p.getCommittedHoursPerDay()
.entrySet()
.stream())
.filter(mapEntry -> mapEntry.getValue() >= 8)
.collect(Collectors.toMap(mapEntry -> mapEntry.getKey(), mapEntry -> mapEntry.getValue()));
The flatMap
step returns a Stream<Map.Entry<Employee, Integer>>
. The filter
thus operates on a Map.Entry<Employee, Integer>
.
You can also use method reference on the collect step as .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))