Home > Enterprise >  Sort the List based on 2 fields if the first field has more than 1 matching record
Sort the List based on 2 fields if the first field has more than 1 matching record

Time:01-19

I have a table with the below info

Id Name EmpDate AwardsReceived
1 Tom 1/19/2023 1
2 Jerry 1/19/2023 2
3 Peppa 1/18/2023 1

Consider I have the above data in a list EmployeeList. I wanted to sort the list based on Empdate first and if there is more than 1 employee with the same latest date, then I want to sort them with the awardsReceived and get the latest one from the list.

So , from the above data, I want to get Jerry using java8 streams.

I have tried the below code but, its not working as expected.

Optional <Employee> employee = employeeList.stream()                                                                                                                                                 .sorted(Comparator.comparing(Employee::getEmpDate).reversed())                                                                     .sorted(Comparator.comparing(Employee::getAwardsReceived).reversed()).findFirst();

Please suggest the valid approach.

CodePudding user response:

You can achieve it using the below sample code. Let me know if it doesn't works.

employeeList.stream()
.sorted((e1, e2) -> e2.getEmpDate().compareTo(e1.getEmpDate()))
.sorted((e1, e2) -> Integer.compare(e2.getAwardsReceived(), e1.getAwardsReceived()))

CodePudding user response:

You should be using LocalDate for the dates since string dates will not compare chronologically but lexically. But here is how you would accomplish it.

I am using a record, which is an immutable class so either would work. I am also converting the date to LocalDate

record Employee(int id, String name, LocalDate date, int awards) {
     public Employee (int id, String name, String date, int awards) {
         this(id, name, LocalDate.parse(date, 
                DateTimeFormatter.ofPattern("M/dd/yyyy")), awards);
     }
 }

List<Employee> employeeList = List.of(
         new Employee(1, "Tom",   "1/19/2023", 1),
         new Employee(4, "Mary",  "1/19/2023", 1),
         new Employee(5, "Bob",   "1/14/2023", 2),
         new Employee(2, "Jerry", "1/19/2023", 2),
         new Employee(3, "Peppa", "1/13/2023", 3));
  • First compare on the employee date using a Comparator. Most recent dates would be sorted first as their natural order.
  • if two are equal, then sort on the employee awards in reverse order (to get the max awards first).
  • the use findFirst to get the first occurrence and retrieve it from the Optional
Employee match = employeeList.stream()
         .sorted(Comparator.comparing(Employee::date).thenComparing(
         Employee::awards).reversed())
         .findFirst().get();

System.out.println(match);

prints

Employee[id=2, name=Jerry, date=2023-01-19, awards=2]
  • Related