I have a List of Procedure objects as below
Procedure1 01/01/2020
Procedure2 03/01/2020
Procedure3 03/01/2020
Procedure1 04/01/2020
Procedure5 05/01/2020, 02/01/2020
Procedure2 06/01/2020
and my Procedure class is like
Class Procedure {
List<Date> procedureDate;
String procedureName;
}
I want to sort and group the objects based on the below conditions.
- All procedures should be grouped based on the procedure name.
- Procedures must be in descending order of procedure date. [first element in date list i.e.,
procedureDate.get[0]] - Same Procedures grouped together should be in descending order of Date.
End result must be,
Procedure2 06/01/2020
Procedure2 03/01/2020
Procedure5 05/01/2020, 02/01/2020
Procedure1 04/01/2020
Procedure1 01/01/2020
Procedure3 03/01/2020
I was able to achieve this using Comparator and old java code. Is it possible to achieve the same using java8 streams, collectors and grouping by?
This is a very interesting question. The solution is not as easy as it looks to be. You have to divide the solution into multiple steps:
procedureNamebased on the first dates in theList<Date>.Procedureinstances based on maxDatevalue from theMap<String, Datecreated in the step one.Procedure 2).Procedureinstances based on their actual first date.Here is the demo at: https://www.jdoodle.com/iembed/v0/Te.
Step 1
.. explained: There is a simple way to get a
Procedurewith maximum first date grouped byprocedureName.However, the returned structure is a bit clumsy (
Map<String, Optional<Procedure>>), to make it useful and returnDatedirectly, there is a need of additional downstream collectorCollectors::collectingAndThenwhich uses aFunctionas a result mapper:... which is effectively the first snippet.
Steps 2, 3 and 4
Basically, sort by the maximum date for each group. Then sort by the name and finally by the actual first date.
Sorted result
Using the deprecated
java.util.Dateaccording to your question, the sortedprocedureswill have sorted items like your expected snippet (I have overrided theProcedure::toStringmethod)