Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在日期列表中查找距离目标最近日期的最佳方法?_Java_Date - Fatal编程技术网

Java 在日期列表中查找距离目标最近日期的最佳方法?

Java 在日期列表中查找距离目标最近日期的最佳方法?,java,date,Java,Date,我有一个日期对象列表和目标日期。我想在列表中查找最接近目标日期的日期,但只查找目标日期之前的日期 例如: 2008-10-1 2008-10-2 2008-10-4 目标日期为2008-10-3,我想得到2008-10-2 最好的方法是什么?我目前使用以下方法,但我不确定这是最有效的方法,因为这假设一个已经排序的列表,并且(可能)迭代列表中的每个日期 private Date getDateNearest(List<Date> dates, Date targetDate){ f

我有一个日期对象列表和目标日期。我想在列表中查找最接近目标日期的日期,但只查找目标日期之前的日期

例如: 2008-10-1 2008-10-2 2008-10-4

目标日期为2008-10-3,我想得到2008-10-2


最好的方法是什么?

我目前使用以下方法,但我不确定这是最有效的方法,因为这假设一个已经排序的列表,并且(可能)迭代列表中的每个日期

private Date getDateNearest(List<Date> dates, Date targetDate){
  for (Date date : dates) {
    if (date.compareTo(targetDate) <= 0) return date;
  }

  return targetDate;
}
private Date getDateNearest(列出日期、日期targetDate){
用于(日期:日期){
if(date.compareTo(targetDate)
private date getDateNearest(列出日期,日期targetDate){
返回新树集(日期)。降低(目标日期);
}

不需要预先排序的列表,TreeSort解决了这一问题。但如果找不到,它将返回null,因此如果出现问题,您将不得不修改它。也不确定效率:p

Sietse de Kaper解决方案假设一个反向排序的列表,这肯定不是最自然的事情

java中的自然排序顺序遵循升序自然排序。(请参阅Collection.sort文档)

从你的例子来看

target date = 2008-10-03 list = 2008-10-01 2008-10-02 2008-10-04 目标日期=2008-10-03 列表=2008-10-012008-10-022008-10-04 如果另一个开发人员以一种幼稚的方式使用您的方法,他将得到2008-10-01,这不是预期的结果

  • 不要对列表的顺序进行假设。
  • 如果出于性能原因必须这样做,请尝试遵循最自然的惯例(按升序排序)
  • 如果你真的要遵守另一个惯例,你真的应该把它记录下来

    private Date getDateNearest(List<Date> dates, Date targetDate){
      Date returnDate = targetDate
      for (Date date : dates) {
        // if the current iteration'sdate is "before" the target date
        if (date.compareTo(targetDate) <= 0) {
          // if the current iteration's date is "after" the current return date
          if (date.compareTo(returnDate) > 0){
            returnDate=date;
          }
        }
      }  
      return returnDate;
    }
    
    private Date getDateNearest(列出日期、日期targetDate){
    日期返回日期=目标日期
    用于(日期:日期){
    //如果当前迭代的日期在目标日期之前
    
    if(date.compareTo(targetDate)尽管Keeg的答案在1.5的1.6中有效,但没有更低的方法()

    这个在1.5版本中有效

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.TreeSet;
    
    public class GetNearestDate {
    
      public static void main( String[] args ) throws ParseException {
    
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat( "dd.MM.yyyy HH:mm:ss" );
    
        List< Date > otherDates = Arrays.asList( new Date[]{
          simpleDateFormat.parse( "01.01.2008 01:00:00" ) ,
          simpleDateFormat.parse( "01.01.2008 01:00:02" ) } );
        System.out.println( simpleDateFormat.parse( "01.01.2008 01:00:00" ).equals(
          get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:01" ) ) ) );
        System.out.println( simpleDateFormat.parse( "01.01.2008 01:00:02" ).equals(
          get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:03" ) ) ) );
        System.out.println( null == get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:00" ) ) );
      }
    
      public static Date get( List< Date > otherDates , Date dateToApproach ) {
        final TreeSet< Date > set = new TreeSet< Date >( otherDates );
        set.add( dateToApproach );
        final ArrayList< Date > list = new ArrayList< Date >( set );
        final int indexOf = list.indexOf( dateToApproach );
        if ( indexOf == 0 )
          return null;
        return list.get( indexOf - 1 );
      }
    
    }
    
    import java.text.ParseException;
    导入java.text.simpleDataFormat;
    导入java.util.ArrayList;
    导入java.util.array;
    导入java.util.Date;
    导入java.util.List;
    导入java.util.TreeSet;
    公共类GetNearestDate{
    公共静态void main(字符串[]args)引发异常{
    最终SimpleDateFormat SimpleDateFormat=新SimpleDateFormat(“dd.MM.yyyy HH:MM:ss”);
    ListotherDates=Arrays.asList(新日期[]{
    SimpleDataFormat.parse(“01.01.2008 01:00:00”),
    simpleDataFormat.parse(“01.01.2008 01:00:02”);
    System.out.println(simpleDataFormat.parse(“01.01.2008 01:00:00”)。等于(
    get(otherDates,simpleDateFormat.parse(“01.01.2008 01:00:01”));
    System.out.println(simpleDataFormat.parse(“01.01.2008 01:00:02”)。等于(
    get(otherDates,simpleDateFormat.parse(“01.01.2008 01:00:03”));
    System.out.println(null==get(其他日期,SimpleDataFormat.parse(“01.01.2008 01:00:00”));
    }
    公共静态日期获取(列表<日期>其他日期,日期日期接近){
    最终树集<日期>集=新树集<日期>(其他日期);
    set.add(dateToApproach);
    最终ArrayList列表=新ArrayList(设置);
    final int indexOf=list.indexOf(dateToApproach);
    如果(indexOf==0)
    返回null;
    returnlist.get(indexOf-1);
    }
    }
    
    您看过JodaTime API吗?我似乎记得有这样一个功能可用。

    NavigableSet::lower
    这个方法非常简洁,其思想是利用接口中定义并在类中实现的方法

    但与其他答案一样,它使用了与最早版本的Java捆绑在一起的过时的日期时间类

    旧的问题和答案要么使用
    java.util.Date
    表示日期和时间,要么使用
    java.sql.Date
    笨拙地扩展util.Date,同时假装它没有一天的时间。一团混乱

    java.time 那些麻烦的旧类已经被内置在Java 8和更高版本中的类所取代。请参阅。许多功能已在中重新移植到Java 6和7,并在中进一步适用于Android

    LocalDate
    该类表示一个仅日期的值,不包含一天中的时间,也不包含时区。虽然这些对象不存储时区,但请注意,时区()在确定当前日期时至关重要。对于任何给定时刻,日期在全球各地随时区而变化

    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    LocalDate today = LocalDate.now( zoneId );  // 2016-06-25
    
    ISO 8601 提示:用前导零填充这些月和月日数字。这使它们符合标准日期-时间格式。在java.time中解析/生成表示日期-时间值的字符串时默认使用这些格式

    因此,请使用
    2008-10-01
    而不是
    2008-10-1
    。如果填充不可行,请使用解析


    这将花费对列表nlog(n)进行排序,然后在列表中查找元素(treesort文档中的log(n))以及所有这些的代价,而仅仅是为了抛出已排序的集合。(请注意,集合不支持重复项,在这里无关紧要,但它可能会影响其他地方)@Keeg完美解决方案为什么要使用treeset?otherDates.add(datetoapproach);Collection.sort(ortherDate);indexOf magic和remove datetoapproach…嗯,我在咖啡休息时想到的第一个方法,尽管我确信,Collection.sort也会起作用;-)
    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    LocalDate today = LocalDate.now( zoneId );  // 2016-06-25
    
    NavigableSet dates = new TreeSet( 3 );
    dates.add( LocalDate.parse( "2008-10-01" );
    dates.add( LocalDate.parse( "2008-10-02" );
    dates.add( LocalDate.parse( "2008-10-04" );
    LocalDate target = LocalDate.parse( "2008-10-03" );
    LocalDate hit = dates.lower( target );
    // Reminder: test for `null == hit` to see if anything found.