Java 在日期列表中查找距离目标最近日期的最佳方法?
我有一个日期对象列表和目标日期。我想在列表中查找最接近目标日期的日期,但只查找目标日期之前的日期 例如: 2008-10-1 2008-10-2 2008-10-4 目标日期为2008-10-3,我想得到2008-10-2Java 在日期列表中查找距离目标最近日期的最佳方法?,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
最好的方法是什么?我目前使用以下方法,但我不确定这是最有效的方法,因为这假设一个已经排序的列表,并且(可能)迭代列表中的每个日期
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,因此如果出现问题,您将不得不修改它。也不确定效率:pSietse 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.