Java排序逻辑和识别两个对象中的最大值

huangapple go评论74阅读模式
英文:

Java Sorting logic and Identifying max of two objects

问题

要求是找到具有部门2中组号为8且在部门2中具有组号为4的最新员工对象(最新日期)。同样地,要在部门1中找到组号为8且在部门1中具有组号为4的情况。我只需要在最终列表中保留上述所有情况中的一个最新对象。

编写的比较逻辑是按照所需的顺序进行排序,并仅保留所需的对象。但是我陷入了困境,因为我无法找到一种从排序列表中保留单个对象的方法。是否有任何方法可以实现这一点?请忽略比较器逻辑,如果您可以建议使用流或其他良好的实现方式,我将不胜感激。

  SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy");
    List<Employee> employees = new LinkedList<>(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;
      }
    });

英文:

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(&quot;dd-mm-yyyy&quot;);
List&lt;Employee&gt; employees = new LinkedList&lt;Employee&gt;(Arrays.asList(
new Employee(&quot;Emp1&quot;, df.parse(&quot;12-08-2020&quot;),
new EmpType(&quot;1&quot;, new Group(8))),
new Employee(&quot;Emp2&quot;, df.parse(&quot;11-08-2020&quot;),
new EmpType(&quot;2&quot;, new Group(8))),
new Employee(&quot;Emp3&quot;, df.parse(&quot;10-08-2020&quot;),
new EmpType(&quot;2&quot;, new Group(4))),
new Employee(&quot;Emp4&quot;, df.parse(&quot;17-08-2020&quot;),
new EmpType(&quot;2&quot;, new Group(8))),
new Employee(&quot;Emp5&quot;, df.parse(&quot;19-08-2020&quot;),
new EmpType(&quot;1&quot;, new Group(4)))));
/* Sorting logic to sort by group number first then by department and then by date */
Collections.sort(employees, new Comparator&lt;Employee&gt;() {
@Override
public int compare(Employee employee, Employee t1) {
int val = 0;
if (employee.getEmpType().getGroup().getNumber() &lt; t1.getEmpType().getGroup().getNumber()) {
val = 1;
} else if (employee.getEmpType().getGroup().getNumber() &gt; 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;
}
});

答案1

得分: 2

代替排序,您可以使用与您实现的相同“Comparator”的Collections.max

编辑以回应评论中的讨论:
如果我正确理解数据结构,EmpType 封装了我们想要找到“最新”雇员的唯一组合。假设它对 equals(Object)hashCode() 方法有适当的实现,您可以对列表进行流式处理,并将其收集到从 EmpType 到最新雇员的映射中:

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

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

EDIT to address the discussion in the comments:<br/>
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&lt;EmpType, Employee&gt; latestEmployees =
    employees.stream()
             .collect(Collectors.toMap(
                          Employee::getEmpType,
                          Function.identity(),
                          BinaryOperator.maxBy(
                              Comparator.comparing(Employee::getDate))));



</details>



# 答案2
**得分**: 1

我觉得在排序函数内部混合业务逻辑相当混乱

为什么不只是根据员工的日期降序排列然后在结果数组中遍历直到第一次满足您的条件为止

<details>
<summary>英文:</summary>

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?

</details>



# 答案3
**得分**: 1

你可以使用 Stream API 的 `Collectors.toMap` 方法按照 `EmpType` 进行分组并使用 `BinaryOperator.maxBy` 获取每个具有相同 `EmpType` 的分组的最新日期作为值然后将 map 的值取出放入一个新的 `ArrayList`在这里按照 `EmpType` 进行分组因为它包含了组号和部门信息你需要为 `EmpType` 实现适当的 `equals``hashcode` 方法

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

或者你可以创建一对组号和部门的组合作为键,例如使用 new AbstractMap.SimpleEntry(e.getEmpType().getDepartment(), e.getEmpType().getGroup().getNumber()),代替使用 EmpType 作为键,这样就不需要实现 equalshashcode 方法。

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());
英文:

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&lt;Employee&gt; 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&lt;Employee&gt; res = new ArrayList(employees.stream()
.collect(Collectors.toMap(
e -&gt; new AbstractMap.SimpleEntry(e.getEmpType().getDepartment(),
e.getEmpType().getGroup().getNumber()),
Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Employee::getDate))))
.values());

huangapple
  • 本文由 发表于 2020年9月12日 18:49:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/63859540.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定