这是一个非常有趣的问题。解决方案并不像看起来那么容易。您必须将解决方案分为多个步骤:
- 根据.
procedureName
_List<Date>
- 根据第一步中创建的最大值比较
Procedure
实例。Date
Map<String, Date
- 如果它们相等,请按名称区分它们(例如两次
Procedure 2
)。
- 如果它们仍然相等,请
Procedure
根据它们的实际第一次日期对实例进行排序。
以下是演示:https ://www.jdoodle.com/iembed/v0/Te 。
步骤1
List<Procedure> procedures = ...
Map<String, Date> map = procedures.stream().collect(
Collectors.collectingAndThen(
Collectors.groupingBy(
Procedure::getProcedureName,
Collectors.maxBy(Comparator.comparing(s -> s.getProcedureDate().get(0)))),
s -> s.entrySet().stream()
.filter(e -> e.getValue().isPresent())
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().get().getProcedureDate().get(0)))));
.. 解释:有一种简单的方法可以获取按 .Procedure
分组的最大第一次日期procedureName
。
Map<String, Optional<Procedure>> mapOfOptionalProcedures = procedures.stream()
.collect(Collectors.groupingBy(
Procedure::getProcedureName,
Collectors.maxBy(Comparator.comparing(o -> o.getProcedureDate().get(0)))));
但是,返回的结构有点笨拙(Map<String, Optional<Procedure>>
),为了使它有用并Date
直接返回,需要额外的下游收集器Collectors::collectingAndThen
,它使用 aFunction
作为结果映射器:
Map<String, Date> map = procedures.stream().collect(
Collectors.collectingAndThen(
/* grouping part */,
s -> s.entrySet().stream()
.filter(e -> e.getValue().isPresent())
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().get().getProcedureDate().get(0)))));
...这实际上是第一个片段。
步骤 2、3 和 4
基本上,按每个组的最大日期排序。然后按名称排序,最后按实际的第一次日期排序。
Collections.sort(
procedures,
(l, r) -> {
int dates = map.get(r.getProcedureName()).compareTo(map.get(l.getProcedureName()));
if (dates == 0) {
int names = l.getProcedureName().compareTo(r.getProcedureName());
if (names == 0) {
return r.getProcedureDate().get(0).compareTo(l.getProcedureDate().get(0));
} else return names;
} else return dates;
}
);
排序结果
java.util.Date
根据您的问题使用不推荐使用的,procedures
排序后的项目将像您预期的片段一样排序(我已经覆盖了该Procedure::toString
方法)
@Override
public String toString() {
return procedureName + " " + procedureDate;
}
Procedure2 [Mon Jan 06 00:00:00 CET 2020]
Procedure2 [Fri Jan 03 00:00:00 CET 2020]
Procedure5 [Sun Jan 05 00:00:00 CET 2020, Thu Jan 02 00:00:00 CET 2020]
Procedure1 [Sat Jan 04 00:00:00 CET 2020]
Procedure1 [Wed Jan 01 00:00:00 CET 2020]
Procedure3 [Fri Jan 03 00:00:00 CET 2020]