按组排序,然后根据组在两个字段上排序

时间:2019-07-09 11:58:47

标签: java sorting java-8

我想根据三个字段对对象列表进行排序。首先,它属于哪个组,然后根据它属于哪个组,对两个不同的日期字段进行排序。

假设我们有一个对象Case,其中包含三个字段String statusLocalDate startedDateLocalDate deletedDate。状态可以是"Active""Deleted",而startedDatedeletedDate是日期。 Case的{​​{1}}有一个deletedDate

对于使用以下规则对对象列表进行排序的一个好的解决方案,任何人都有想法:

  • 首先对状态进行排序
  • 如果状态为“有效”,则按startDate降序排列。
  • 如果状态为“已删除”,则按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

2 个答案:

答案 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