按LocalDate降序和LocalTime升序对列表进行排序

时间:2020-06-15 16:29:32

标签: java list sorting date comparator

我有一个带有LocalDateTime字段的对象列表。
我想按日期和时间特别对所有这些对象进行排序。

我解释了应该怎么做:

按日期降序排列但按时间升序

这里是一个例子:

未排序LocalDateTime

  • 2016-10-06T09:10
  • 2016-10-06T10:34
  • 2016-12-06T11:15
  • 2016-11-06T10:34
  • 2016-12-06T10:10
  • 2016-12-06T06:56

应按以下顺序排序:

  1. 2016-12-06T06:56
  2. 2016-12-06T10:10
  3. 2016-12-06T11:15
  4. 2016-11-06T10:34
  5. 2016-10-06T09:10
  6. 2016-10-06T10:34

请记住,我需要对带有字段的对象进行排序,而不是对LocalDateTime的列表进行排序,而对带有LocalDateTime字段的对象列表进行排序。

感谢您对我的帮助:)

1 个答案:

答案 0 :(得分:4)

LocalDateTime对象知道如何按时间顺序对其进行排序。您希望按日期降序排序(按时间倒序,之后的日期排在第一位),又希望按时间升序排序(按时间顺序排序),这意味着该类的compareTo方法实现的内置功能(必需通过Comparable界面)无法完成这项工作。

常规语法

要进行自定义排序,请编写自己的Comparator实现。该接口需要实现一种方法:compare

这里的逻辑很简单:

  • 比较日期部分。
    • 如果两个日期不同,则在此基础上进行反向排序,然后在列表中向下移动。
    • 如果两个日期都相同,则应进行更深的挖掘以比较它们的时间部分,并按时间顺序进行排序。

代码。

package work.basil.example;

import java.time.LocalDateTime;
import java.util.Comparator;

public class LocalDateTimeComparator implements Comparator < LocalDateTime >
{
    @Override
    public int compare ( LocalDateTime o1 , LocalDateTime o2 )
    {
        // Compare the date portion first. If equal, then look at time-of-day.
        int result = o1.toLocalDate().compareTo( o2.toLocalDate() ); // Consider only the date portion first.
        result = ( ( - 1 ) * result ); // Flip the positive/negative sign of the int, to get ascending order. Or more simply: `= - result ;`.
        if ( 0 == result ) // If dates are equal, look at the time-of-day.
        {
            System.out.println( "reversing " );
            result = o1.toLocalTime().compareTo( o2.toLocalTime() );
        }
        return result;
    }
}

使用此比较器尝试示例数据。

List < LocalDateTime > ldts = List.of(
        LocalDateTime.parse( "2016-10-06T09:10" ) ,
        LocalDateTime.parse( "2016-10-06T10:34" ) ,
        LocalDateTime.parse( "2016-12-06T11:15" ) ,
        LocalDateTime.parse( "2016-11-06T10:34" ) ,
        LocalDateTime.parse( "2016-12-06T10:10" ) ,
        LocalDateTime.parse( "2016-12-06T06:56" )
);

List < LocalDateTime > sorted = new ArrayList <>( ldts );
Comparator < LocalDateTime > comparator = new LocalDateTimeComparator();
sorted.sort(  comparator );

转储到控制台。我们看到成功。日期按日期依次为2016年的10月,11月和12月,而一天中的时间为

System.out.println( "ldts = " + ldts );
System.out.println( "sorted = " + sorted );

ldts = [2016-10-06T09:10,2016-10-06T10:34,2016-12-06T11:15,2016-11-06T10:34,2016-12-06T10:10,2016-12- 06T06:56]

sorted = [2016-12-06T06:56,2016-12-06T10:10,2016-12-06T11:15,2016-11-06T10:34,2016-10-06T09:10,2016-10- 06T10:34]

Lambda语法

comment by Ole V.V.显示了如何在现代Java中使用功能性lambda语法进行等效工作。那条评论启发了我尝试功能性方法。

这里的想法是使用两个Comparator对象:一个用于日期,另一个用于一天中的时间。实际上,我们可以通过调用Comparator将一个Comparator::thenComparing嵌套在另一个comparatorDate中。因此,我们需要建立两个比较器,然后将一个提供给另一个。我们实例化一个comparatorTime,然后向其中一个comparatorDateThenTime馈送一个comparatorDateThenTime。我们将sort传递给List < LocalDateTime > ldts = List.of( LocalDateTime.parse( "2016-10-06T09:10" ) , LocalDateTime.parse( "2016-10-06T10:34" ) , LocalDateTime.parse( "2016-12-06T11:15" ) , LocalDateTime.parse( "2016-11-06T10:34" ) , LocalDateTime.parse( "2016-12-06T10:10" ) , LocalDateTime.parse( "2016-12-06T06:56" ) ); List < LocalDateTime > sorted = new ArrayList <>( ldts ); Comparator < LocalDateTime > comparatorDate = Comparator .comparing( ( LocalDateTime ldt ) -> ldt.toLocalDate() ) .reversed(); Comparator < LocalDateTime > comparatorTime = Comparator .comparing( ( LocalDateTime ldt ) -> ldt.toLocalTime() ); Comparator < LocalDateTime > comparatorDateThenTime = comparatorDate .thenComparing( comparatorTime ); sorted.sort( comparatorDateThenTime ); // Dump to console. System.out.println( "ldts = " + ldts ); System.out.println( "sorted = " + sorted ); 方法以实际执行排序工作。

Comparator

ldts = [2016-10-06T09:10,2016-10-06T10:34,2016-12-06T11:15,2016-11-06T10:34,2016-12-06T10:10,2016-12- 06T06:56]

sorted = [2016-12-06T06:56,2016-12-06T10:10,2016-12-06T11:15,2016-11-06T10:34,2016-10-06T09:10,2016-10- 06T10:34]

我们可以使用匿名的Comparator.comparing对象(从对Comparator.reversedList < LocalDateTime > ldts = List.of( LocalDateTime.parse( "2016-10-06T09:10" ) , LocalDateTime.parse( "2016-10-06T10:34" ) , LocalDateTime.parse( "2016-12-06T11:15" ) , LocalDateTime.parse( "2016-11-06T10:34" ) , LocalDateTime.parse( "2016-12-06T10:10" ) , LocalDateTime.parse( "2016-12-06T06:56" ) ); List < LocalDateTime > sorted = new ArrayList <>( ldts ); sorted.sort( Comparator .comparing( ( LocalDateTime ldt ) -> ldt.toLocalDate() ) .reversed() .thenComparing( Comparator .comparing( ( LocalDateTime ldt ) -> ldt.toLocalTime() ) ) ); // Dump to console. System.out.println( "ldts = " + ldts ); System.out.println( "sorted = " + sorted ); 的调用返回的单行处理中将所有内容整合在一起。

LocalDateTime

ldts = [2016-10-06T09:10,2016-10-06T10:34,2016-12-06T11:15,2016-11-06T10:34,2016-12-06T10:10,2016-12- 06T06:56]

sorted = [2016-12-06T06:56,2016-12-06T10:10,2016-12-06T11:15,2016-11-06T10:34,2016-10-06T09:10,2016-10- 06T10:34]

我想我更希望在生产代码中看到第一个,即多行代码。但我不确定。

问题中陈述的实际问题涉及Happening作为另一个类的成员字段。因此,让我们扩展解决方案以包括该嵌套类。在这里,我们发明了一个LocalDateTime类,该类由带有package work.basil.example; import java.time.LocalDateTime; import java.util.Objects; public class Happening { private String description; private LocalDateTime localDateTime; public Happening ( String description , LocalDateTime localDateTime ) { this.description = Objects.requireNonNull( description ); this.localDateTime = Objects.requireNonNull( localDateTime ); } public String getDescription ( ) { return this.description; } public LocalDateTime getLocalDateTime ( ) { return this.localDateTime; } @Override public String toString ( ) { return "Happening{ " + "description='" + description + '\'' + " | localDateTime=" + localDateTime + " }"; } } 对象的描述字符串组成。

LocalDateTime

让我们收集这些对象,并使用与上面类似的代码进行排序。我们必须再走一步,从每个Happening对象中提取一个List < Happening > happenings = List.of( new Happening( "aaa" , LocalDateTime.parse( "2016-10-06T09:10" ) ) , new Happening( "bbb" , LocalDateTime.parse( "2016-10-06T10:34" ) ) , new Happening( "ccc" , LocalDateTime.parse( "2016-12-06T11:15" ) ) , new Happening( "ddd" , LocalDateTime.parse( "2016-11-06T10:34" ) ) , new Happening( "eee" , LocalDateTime.parse( "2016-12-06T10:10" ) ) , new Happening( "fff" , LocalDateTime.parse( "2016-12-06T06:56" ) ) ); List < Happening > sorted = new ArrayList <>( happenings ); sorted.sort( Comparator .comparing( ( Happening happening ) -> happening.getLocalDateTime().toLocalDate() ) .reversed() .thenComparing( Comparator .comparing( ( Happening happening ) -> happening.getLocalDateTime().toLocalTime() ) ) ); // Dump to console. System.out.println( "happenings = " + happenings ); System.out.println( "sorted = " + sorted ); 对象。

{{1}}

运行时,我们从a-b-c-d-e-f转到f-e-c-d-a-b顺序。

事件= [发生{description ='aaa'| localDateTime = 2016-10-06T09:10},正在发生{description ='bbb'| localDateTime = 2016-10-06T10:34},正在发生{description ='ccc'| localDateTime = 2016-12-06T11:15},正在发生{description ='ddd'| localDateTime = 2016-11-06T10:34},正在发生{description ='eee'| localDateTime = 2016-12-06T10:10},正在发生{description ='fff'| localDateTime = 2016-12-06T06:56}]

sorted = [发生{description ='fff'| localDateTime = 2016-12-06T06:56},正在发生{description ='eee'| localDateTime = 2016-12-06T10:10},正在发生{description ='ccc'| localDateTime = 2016-12-06T11:15},正在发生{description ='ddd'| localDateTime = 2016-11-06T10:34},正在发生{description ='aaa'| localDateTime = 2016-10-06T09:10},正在发生{description ='bbb'| localDateTime = 2016-10-06T10:34}]