Java Sorting logic and Identifying max of two objects

Viewed 91

The requirement is to find the latest employee objects (latest date) having group number 8 with department 2 and having group number 4 within department 2. Same way group number 8 within department 1 and group number 4 in department 1. I only need the latest one object of all the above in the final list.

The comparison logic written was to sort it on the required order and retain only the required object. But I am stuck as I cannot find a way to retain single object from the sorted list. Is there anyway i can achieve it? Ignore the Comparator logic, appreciate if you can suggest any ootb way using stream or other good implementation?

  SimpleDateFormat df = new SimpleDateFormat("dd-mm-yyyy");
    List<Employee> employees = new LinkedList<Employee>(Arrays.asList(
        new Employee("Emp1", df.parse("12-08-2020"),
            new EmpType("1", new Group(8))),
        new Employee("Emp2", df.parse("11-08-2020"),
            new EmpType("2", new Group(8))),
        new Employee("Emp3", df.parse("10-08-2020"),
            new EmpType("2", new Group(4))),
        new Employee("Emp4", df.parse("17-08-2020"),
            new EmpType("2", new Group(8))),
        new Employee("Emp5", df.parse("19-08-2020"),
            new EmpType("1", new Group(4)))));


    /* Sorting logic to sort by group number first then by department and then by date */
    Collections.sort(employees, new Comparator<Employee>() {
      @Override
      public int compare(Employee employee, Employee t1) {
        int val = 0;
        if (employee.getEmpType().getGroup().getNumber() < t1.getEmpType().getGroup().getNumber()) {
          val = 1;
        } else if (employee.getEmpType().getGroup().getNumber() > t1.getEmpType().getGroup()
            .getNumber()) {
          val = -1;
        } else {
          val = 0;
        }

        if (val == 0) {
          val = -(employee.getEmpType().getDepartment().compareTo(t1.getEmpType().getDepartment()));
        }
        if (val == 0) {
          val = -employee.getDate().compareTo(t1.getDate());
        }
        return val;
      }
    });

3 Answers

Instead of sorting, you could use Collections.max with the same Comparator you've implemented.

EDIT to address the discussion in the comments:
If I understand the data structure correctly, EmpType encapsulates the unique combination we want to find the "latest" employee for. Assuming it has a proper implementation of the equals(Object) and hashCode() methods, you could stream the list and collect it to a map from the EmpType to the latest employee:

Map<EmpType, Employee> latestEmployees =
    employees.stream()
             .collect(Collectors.toMap(
                          Employee::getEmpType,
                          Function.identity(),
                          BinaryOperator.maxBy(
                              Comparator.comparing(Employee::getDate))));

I find it quite messy to mix the business logic inside the sort function.

Why not just sort the Employees descendingly accoring to their date and parse through the resulting array untill your conditions are met for the first time?

You can use Collectors.toMap of Stream API to map by EmpType and get the latest date for each group having the same EmpType using BinaryOperator.maxBy as values. Then get the values of map in new ArrayList. Here map by EmpType because it contains group number and department and you need proper equals and hashcode implementation for EmpType.

List<Employee> res = new ArrayList(employees.stream()
    .collect(Collectors.toMap(Employee::getEmpType, Function.identity(),
        BinaryOperator.maxBy(Comparator.comparing(Employee::getDate)))).values());

or you can create pair of group number and department like new AbstractMap.SimpleEntry(e.getEmpType().getDepartment(), e.getEmpType().getGroup().getNumber()) as key instead of EmpType then don't need equals and hashcode implementation

List<Employee> res = new ArrayList(employees.stream()
        .collect(Collectors.toMap(
                         e -> new AbstractMap.SimpleEntry(e.getEmpType().getDepartment(),
                                                  e.getEmpType().getGroup().getNumber()),
                                  Function.identity(),
                        BinaryOperator.maxBy(Comparator.comparing(Employee::getDate))))
        .values());
Related