按开始和结束时间过滤带有日期的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
类表示没有时间且没有时区的仅日期值。 切勿使用Date
, Calendar
, SimpleDateFormat
或其他可怕的旧遗留日期时间类。
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.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
- Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11及更高版本 – 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和Java 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的试验场。 您可以在这里找到一些有用的课程,如Interval
, YearWeek
, YearQuarter
等。