按开始和结束时间筛选具有日期的ArrayList



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

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

a。使用Java 8过滤器,其中包含开始日期和结束日期。

b。使用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<Date> dateList = null;
    private Date start = null;
    private Date end = null;
    private FilterStartAndEndDate() throws ParseException {
        dateList = new ArrayList<Date>() {{
            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<Date> 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();
    }
}

示例代码过滤器的日期为一月份,使用Lambda过滤器和Java迭代器。两者都使用Date before和Date after方法。

定义一个类

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

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

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。通常最好使用半开放方法进行比较,其中开头为包含,结尾为exclusive

    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,而不是用于每个循环。同样的效果;使用您喜欢的任何语法方法。

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

为了示范起见,把所有这些放在一个大班里。我不会在实际工作中嵌套这个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-02-23 |停止=2018-02-28}]

LocalDateRange

如果你想获得灵感,请将ThreeTen Extra库(下面讨论)添加到你的项目中。使用其LocalDateRange类将您的停止-开始日期对明确表示为日期范围。该类已经包含了一个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'|日期范围=2018-02-23/2018-02-28}]


关于java.time

java.time框架构建在Java8及更高版本中。这些类取代了诸如java.util.DateCalendar、&SimpleDateFormat

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

要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。规范是JSR310。

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

从哪里获得java.time类?

  • Java SE 8Java SE 9Java SE 10爪哇SE 11及更高版本-标准Java API的一部分,具有捆绑实现。
    • Java 9添加了一些小功能和修复程序
  • Java SE 6Java SE 7
    • 大部分java.time功能都是向后移植到Java6&7英寸ThreeTen背包
  • 安卓
    • java.time类的Android捆绑包实现的后续版本
    • 对于早期的Android(<26),ThreeTenABP项目适用于ThreeTen Backport(如上所述)。请参阅如何使用ThreeTenABP…

ThreeTen Extra项目通过附加类扩展java.time。这个项目是将来可能添加到java.time的试验场。您可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等等。

最新更新