Reputation: 1329
I have a
class MedicationPeriod {
LocalDateTime startDate, endDate;
//assume getters and setters
}
Then I have a List<MedicationPeriod> medPrd = getMedPeriods();
Elements in medPrd
may have the same startDate.
Now I want to filter the list such that, for elements having the same startDate, the one with the greatest endDate should remain in the list. I.e. having the longest day.
Example: If list elements are:
1) startDate = 2018-Jan-1, endDate = 2018-Feb-25 // 25 days
2) startDate = 2018-Jan-1, endDate = 2018-Feb-20 // 20 days
3) startDate = 2018-Jan-5, endDate = 2018-Feb-25 // startDate is diff, we don't care
So the final list should have only elements 1) and 3). Element 2 will be removed since other MedicationPeriod with the same startDate has a greater endDate.
Here is my attempt (non happily working) to get the result:
mps.stream().collect(Collectors.toMap(MedicationPeriod::getStartDate, e -> e, (a,b) -> a.endDate.isAfter(b.endDate) ? a : b)).values();
My requirement:
I want List<MedicationPeriod>
not Collection<MedicationPeriod>
as my solution gives Collection<>
I want to achieve this without collecting them and using .values()
, because I may do further transformations while in streams and collecting them later.
Let's say I have to perform some test after filtering the MedicationPeriods and then collect it into:
class DateRange {
LocalDate startDate, endDate;
}
How can I do this with only one terminal operation?
Upvotes: 2
Views: 143
Reputation: 27038
There is nothing wrong with your code. It works. Just did a bit of refactoring
new ArrayList<>(medPrd.stream()
.collect(Collectors.toMap(MedicationPeriod::getStartDate, Function.identity(), (a, b) -> a.endDate.isAfter(b.endDate) ? a : b))
.entrySet()
.stream()
.map(entry -> new DateRange(entry.getValue().startDate, entry.getValue().getEndDate())).collect(Collectors.toList()));
Incorporating @Holger 's suggestion it would look like
new ArrayList<>(medPrd.stream()
.collect(Collectors.toMap(MedicationPeriod::getStartDate, Function.identity(), BinaryOperator.maxBy(Comparator.comparing(MedicationPeriod::getEndDate))))
.entrySet()
.stream()
.map(entry -> new DateRange(entry.getValue().startDate, entry.getValue().getEndDate())).collect(Collectors.toList()));
Upvotes: 3