按 LocalDate 降序和 LocalTime 升序对列表进行排序
Sort list by LocalDate descending and LocalTime ascending
我有一个包含 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
应按以下顺序排序:
- 2016-12-06T06:56
- 2016-12-06T10:10
- 2016-12-06T11:15
- 2016-11-06T10:34
- 2016-10-06T09:10
- 2016-10-06T10:34
请记住,我需要使用字段对对象进行排序,而不是 LocalDateTime
的列表,而是具有 LocalDateTime
字段的对象列表。
谢谢你帮助我:)
LocalDateTime
objects know how to sort themselves chronologically. Your desire to sort by date descending (reverse chronological, later dates come first) yet also sort secondarily by time-of-day ascending (chronological) means the built-in functionality of the class’ implementation of compareTo
method (required by the Comparable
接口) 无法完成工作。
常规语法
对于自定义排序,编写您自己的 Comparator
implementation. That interface requires one method be implemented: 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 年的十月、十一月和十二月日期顺序排列,而时间
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 语法
展示了如何在现代 Java 中使用函数式 lambda 语法进行等效工作。该评论启发了我尝试函数式方法。
这里的想法是使用两个 Comparator
对象:一个用于日期,一个用于时间。实际上,我们可以通过调用 Comparator::thenComparing
将一个 Comparator
嵌套在另一个中。所以我们需要建立两个比较器,然后将一个提供给另一个。我们实例化一个 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 );
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.reversed
返回的匿名 Comparator
对象,使用一行代码将所有内容整合在一起。
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 );
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 );
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]
我想我更愿意在生产代码中看到第一个,即多行代码。但我不确定。
问题中陈述的真正问题涉及 LocalDateTime
作为另一个 class 的成员字段。因此,让我们扩展我们的解决方案以包括嵌套 class。这里我们发明了一个 Happening
class 由一个带有 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 +
" }";
}
}
让我们收集这些对象,并使用与上述类似的代码进行排序。我们必须多走一步,从每个 Happening
对象中提取一个 LocalDateTime
对象。
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 );
当 运行 我们从 a-b-c-d-e-f 到 f-e-c-d-a-b 顺序。
happenings = [Happening{ description='aaa' | localDateTime=2016-10-06T09:10 }, Happening{ description='bbb' | localDateTime=2016-10-06T10:34 }, Happening{ description='ccc' | localDateTime=2016-12-06T11:15 }, Happening{ description='ddd' | localDateTime=2016-11-06T10:34 }, Happening{ description='eee' | localDateTime=2016-12-06T10:10 }, Happening{ description='fff' | localDateTime=2016-12-06T06:56 }]
sorted = [Happening{ description='fff' | localDateTime=2016-12-06T06:56 }, Happening{ description='eee' | localDateTime=2016-12-06T10:10 }, Happening{ description='ccc' | localDateTime=2016-12-06T11:15 }, Happening{ description='ddd' | localDateTime=2016-11-06T10:34 }, Happening{ description='aaa' | localDateTime=2016-10-06T09:10 }, Happening{ description='bbb' | localDateTime=2016-10-06T10:34 }]
我有一个包含 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
应按以下顺序排序:
- 2016-12-06T06:56
- 2016-12-06T10:10
- 2016-12-06T11:15
- 2016-11-06T10:34
- 2016-10-06T09:10
- 2016-10-06T10:34
请记住,我需要使用字段对对象进行排序,而不是 LocalDateTime
的列表,而是具有 LocalDateTime
字段的对象列表。
谢谢你帮助我:)
LocalDateTime
objects know how to sort themselves chronologically. Your desire to sort by date descending (reverse chronological, later dates come first) yet also sort secondarily by time-of-day ascending (chronological) means the built-in functionality of the class’ implementation of compareTo
method (required by the Comparable
接口) 无法完成工作。
常规语法
对于自定义排序,编写您自己的 Comparator
implementation. That interface requires one method be implemented: 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 年的十月、十一月和十二月日期顺序排列,而时间
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 语法
这里的想法是使用两个 Comparator
对象:一个用于日期,一个用于时间。实际上,我们可以通过调用 Comparator::thenComparing
将一个 Comparator
嵌套在另一个中。所以我们需要建立两个比较器,然后将一个提供给另一个。我们实例化一个 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 );
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.reversed
返回的匿名 Comparator
对象,使用一行代码将所有内容整合在一起。
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 );
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 );
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]
我想我更愿意在生产代码中看到第一个,即多行代码。但我不确定。
问题中陈述的真正问题涉及 LocalDateTime
作为另一个 class 的成员字段。因此,让我们扩展我们的解决方案以包括嵌套 class。这里我们发明了一个 Happening
class 由一个带有 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 +
" }";
}
}
让我们收集这些对象,并使用与上述类似的代码进行排序。我们必须多走一步,从每个 Happening
对象中提取一个 LocalDateTime
对象。
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 );
当 运行 我们从 a-b-c-d-e-f 到 f-e-c-d-a-b 顺序。
happenings = [Happening{ description='aaa' | localDateTime=2016-10-06T09:10 }, Happening{ description='bbb' | localDateTime=2016-10-06T10:34 }, Happening{ description='ccc' | localDateTime=2016-12-06T11:15 }, Happening{ description='ddd' | localDateTime=2016-11-06T10:34 }, Happening{ description='eee' | localDateTime=2016-12-06T10:10 }, Happening{ description='fff' | localDateTime=2016-12-06T06:56 }]
sorted = [Happening{ description='fff' | localDateTime=2016-12-06T06:56 }, Happening{ description='eee' | localDateTime=2016-12-06T10:10 }, Happening{ description='ccc' | localDateTime=2016-12-06T11:15 }, Happening{ description='ddd' | localDateTime=2016-11-06T10:34 }, Happening{ description='aaa' | localDateTime=2016-10-06T09:10 }, Happening{ description='bbb' | localDateTime=2016-10-06T10:34 }]