按开始和结束时间过滤带有日期的ArrayList

我正在实现一个简单的ListView,其中数据源是一个ArrayList,其中包含Name,Start和End日期。 在iOS中,我会使用一个简单的NSPredicate来过滤数组,但在Android和Java中,我对我应该使用的内容感到困惑。 欢迎任何建议。

您可以使用Date.before和Date.after方法。 这些允许您过滤日期列表(对于特定范围(例如1月)的日期):

一个。 使用带有开始日期和结束日期的Java 8filter。

湾 使用Java循环/迭代器来检查开始和结束日期。

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.stream.Collectors; public class FilterStartAndEndDate { private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); private Collection dateList = null; private Date start = null; private Date end = null; private FilterStartAndEndDate() throws ParseException { dateList = new ArrayList() {{ add(sdf.parse("01/01/2016")); add(sdf.parse("02/01/2016")); add(sdf.parse("03/02/2016")); add(sdf.parse("04/01/2016")); add(sdf.parse("05/01/2016")); }}; start = sdf.parse("31/12/2015"); end = sdf.parse("01/02/2016"); } /** * Filter dates with Lambda * * @throws ParseException */ private void getDatesBetweenStartAndFinishWithFilter() throws ParseException { dateList.stream() .filter(dates -> dates.after(start) && dates.before(end)) .collect(Collectors.toList()) .forEach(januaryDate->System.out.println(januaryDate)); } /** * Filter dates with Iterator * * @throws ParseException */ private void getDatesBetweenStartAndFinish() throws ParseException { Collection datesInJanuaryList = new ArrayList<>(); for (Date eachDate : dateList) { if (eachDate.after(start) && eachDate.before(end)) { datesInJanuaryList.add(eachDate); } } for (Date eachDate : datesInJanuaryList) { System.out.println(eachDate); } } public static void main(String[] args) throws Exception { FilterStartAndEndDate datesInJanuary = new FilterStartAndEndDate(); datesInJanuary.getDatesBetweenStartAndFinish(); datesInJanuary.getDatesBetweenStartAndFinishWithFilter(); } } 

示例代码filter的日期为1月,使用Lambdafilter和Java迭代器。 两者都使用方法之前和之后的日期。

定义一个类

包含名称,开始和结束日期

定义一个类来保存您的事件名称,开始日期和停止日期。

LocalDate

将现代java.time类用于日期时间值。 LocalDate类表示没有时间且没有时区的仅日期值。 切勿使用DateCalendarSimpleDateFormat或其他可怕的旧遗留日期时间类。

 class Event { String name; LocalDate start, stop; // Constructor public Event ( String name , LocalDate start , LocalDate stop ) { this.name = name; this.start = start; this.stop = stop; } } 

添加一个方法,将传递的LocalDate与开始和停止日期进行比较,如果包含在我们的日期范围内,则返回true。 通常最好使用半开放方法进行比较,其中开头是包容性的,而结尾是独占的

  public boolean contains ( LocalDate localDate ) { // Regarding the beginning date, a short way of saying2 "is equal to or is later than" is "is not before". boolean x = ( ! localDate.isBefore( this.start ) ) && localDate.isBefore( this.stop ); return x; } 

建立这些事件的列表。

 List< Event > events = new ArrayList<>(); events.add( new Event( "alpha" , LocalDate.of( 2018 , Month.JANUARY , 23 ) , LocalDate.of( 2018 , Month.JANUARY , 28 ) ) ); events.add( new Event( "beta" , LocalDate.of( 2018 , Month.FEBRUARY , 23 ) , LocalDate.of( 2018 , Month.FEBRUARY , 28 ) ) ); events.add( new Event( "gamma" , LocalDate.of( 2018 , Month.MARCH , 23 ) , LocalDate.of( 2018 , Month.MARCH , 28 ) ) ); 

循环这些事件,检查每个事件是否包含我们的目标日期。

 LocalDate target = LocalDate.of( 2018 , Month.FEBRUARY , 25 ); List< Event > hits = new ArrayList<>( events.size() ); for ( Event event : events ) { if ( event.contains( target ) ) { hits.add( event ); } } 

或者,使用带有lambda语法的Java Streams,而不是for-each循环。 同样的效果; 使用任何语法方法都会吸引你。

 LocalDate target = LocalDate.of( 2018 , Month.FEBRUARY , 25 ); List< Event > hits = events .stream() .filter( event -> event.contains( target ) ) .collect( Collectors.toList() ) ; 

为了示范,将所有这些放在一个大的class级里。 我不会将这个Event类嵌套在实际工作中。

 package com.basilbourque.example; import java.time.LocalDate; import java.time.Month; import java.util.ArrayList; import java.util.List; public class ListFilterExample { public static void main ( String[] args ) { ListFilterExample app = new ListFilterExample(); app.doIt(); } private void doIt () { List< Event > events = new ArrayList<>(); events.add( new Event( "alpha" , LocalDate.of( 2018 , Month.JANUARY , 23 ) , LocalDate.of( 2018 , Month.JANUARY , 28 ) ) ); events.add( new Event( "beta" , LocalDate.of( 2018 , Month.FEBRUARY , 23 ) , LocalDate.of( 2018 , Month.FEBRUARY , 28 ) ) ); events.add( new Event( "gamma" , LocalDate.of( 2018 , Month.MARCH , 23 ) , LocalDate.of( 2018 , Month.MARCH , 28 ) ) ); LocalDate target = LocalDate.of( 2018 , Month.FEBRUARY , 25 ); List< Event > hits = new ArrayList<>( events.size() ); for ( Event event : events ) { if ( event.contains( target ) ) { hits.add( event ); } } System.out.println( hits ); } class Event { String name; LocalDate start, stop; public boolean contains ( LocalDate localDate ) { // Regarding the beginning date, a short way of saying2 "is equal to or is later than" is "is not before". boolean x = ( ! localDate.isBefore( this.start ) ) && localDate.isBefore( this.stop ); return x; } // Constructor public Event ( String name , LocalDate start , LocalDate stop ) { this.name = name; this.start = start; this.stop = stop; } @Override public String toString () { return "Event{ " + "name='" + name + '\'' + "| start=" + start + "| stop=" + stop + " }"; } } } 

跑步的时候。

[事件{name =’beta’| 启动= 2018年2月23日| 停止= 2018-02-28}]

LocalDateRange

如果您想获得想象力 ,请将ThreeTen-Extra库(如下所述)添加到您的项目中。 使用其LocalDateRange类将您的stop-start日期明确表示为日期范围。 该类已经包含一个contains方法,所以不需要自己编写。

 package com.basilbourque.example; import org.threeten.extra.LocalDateRange; import java.time.LocalDate; import java.time.Month; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class ListFilterExample { public static void main ( String[] args ) { ListFilterExample app = new ListFilterExample(); app.doIt(); } private void doIt () { List< Event > events = new ArrayList<>(); events.add( new Event( "alpha" , LocalDate.of( 2018 , Month.JANUARY , 23 ) , LocalDate.of( 2018 , Month.JANUARY , 28 ) ) ); events.add( new Event( "beta" , LocalDate.of( 2018 , Month.FEBRUARY , 23 ) , LocalDate.of( 2018 , Month.FEBRUARY , 28 ) ) ); events.add( new Event( "gamma" , LocalDate.of( 2018 , Month.MARCH , 23 ) , LocalDate.of( 2018 , Month.MARCH , 28 ) ) ); LocalDate target = LocalDate.of( 2018 , Month.FEBRUARY , 25 ); // Lambda syntax, instead of for-each loop. List< Event > hits = events.stream().filter( event -> event.contains( target ) ).collect( Collectors.toList() ); System.out.println( hits ); } class Event { String name; LocalDateRange dateRange; public boolean contains ( LocalDate localDate ) { // Regarding the beginning date, a short way of saying2 "is equal to or is later than" is "is not before". boolean x = this.dateRange.contains( localDate ); return x; } // Constructor public Event ( String name , LocalDate start , LocalDate stop ) { this.name = name; this.dateRange = LocalDateRange.of( start , stop ); } @Override public String toString () { return "Event{ " + "name='" + name + '\'' + "| dateRange=" + dateRange + " }"; } } } 

[事件{name =’beta’| dateRange = 2018-02-23 / 2018-02-28}]


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

  • Java SE 8Java SE 9Java SE 10Java SE 11及更高版本 – 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 大多数java.timefunction都在ThreeTen- Backport中反向移植到Java 6和7。
  • Android的
    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android(<26), ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。