我想根据三个字段对对象列表进行排序。首先,它属于哪个组,然后根据它属于哪个组,对两个不同的日期字段进行排序。
假设我们有一个对象Case
,其中包含三个字段String status
,LocalDate startedDate
和
LocalDate deletedDate
。状态可以是"Active"
或"Deleted"
,而startedDate
和deletedDate
是日期。 Case
的{{1}}有一个deletedDate
。
对于使用以下规则对对象列表进行排序的一个好的解决方案,任何人都有想法:
说这是我们开始的数据:
Status == "Deleted"
我尝试这样做,但这并未考虑设置的实际状态:
Name, Created date, Status, Deleted date
xxx, 2019-01-01, Deleted, 2018-02-01
xxx, 2019-01-01, Active, NULL
xxx, 2018-01-01, Deleted, 2019-02-01
xxx, 2018-01-01, Active, NULL
..这将产生以下结果:
cases.sort(Comparator.comparing(Case::getStatus).thenComparing(Case::getCreatedDate).reversed().thenComparing(Case::getDeletedDate).reversed();
这是我对四种情况进行排序时想要的结果:
Name, Created date, Status, Deleted date
xxx, 2019-01-01, Active, NULL
xxx, 2018-01-01, Active, NULL
xxx, 2019-01-01, Deleted, 2019-02-01
xxx, 2018-01-01, Deleted, 2018-02-01
答案 0 :(得分:4)
问题在于,使用您的方法时,您首先要按状态排序,然后按创建日期排序,最后按删除日期排序。考虑到您只需要保留该方法应该起作用的日期比较器,除非元素被无序删除,即,如果e1在e2之前创建,但是e2在e1之后被删除,您将得到错误的顺序。 / p>
要根据元素的状态比较元素,您可以提供一个辅助比较器,该比较器使用状态来确定要比较的属性:
Comparator.comparing( Case::getStatus )
.thenComparing( c -> "Active".equals( c.getStatus() ) ? c.getCreatedDate() : c.getDeletedDate(),
Comparator.reverseOrder() );
编辑:如果所有活动元素的删除日期都为空,则您也可以像以前一样使用2个不同的日期比较器,只是顺序相反:
Comparator.comparing( Case::getStatus )
.thenComparing( Case::getDeletedDate, Comparator.nullsFirst( Comparator.reverseOrder() ) )
.thenComparing( Case::getCreatedDate, Comparator.nullsFirst( Comparator.reverseOrder() ) );
在这里,我们将使用一个事实,即活动元素的nullDeleteDate为空,因此比较的结果将为0。删除的元素首先将按其DeletedDate排序;如果仍然相同,则按其createdDate排序-如果可以的话。
答案 1 :(得分:0)
reversed()必须是thenComparing的参数(使用Comparator.reverseOrder()),否则您将反转整个比较器。
例如像这样:
cases.sort(Comparator
.comparing(Case::getStatus)
.thenComparing(Case::getRelevantDate, Comparator.reverseOrder());
其中getRelevantDate获取相关日期:对于状态==处于活动状态的getCreatedDate,对于状态==已删除的状态的getDeletedDate
当然,如果该方法过于用例所致,那么您也可以将getRelevantDate
作为私有助手方法来实现,在其中定义比较器,然后使用this::getRelevantDate
。