如何查找离指定日期最近的日期?(Java)

8
我希望知道如何编写一个方法来获取最接近指定日期的日期。我的意思是类似以下内容:
public Date getNearestDate(List<Date> dates, Date currentDate) {
    return closestDate  // The date that is the closest to the currentDate;
}

我找到了类似的问题,但只有一个问题得到了很好的回答,而且代码一直给我NullPointerExceptions错误... 有人能帮助我吗?


你最近的日期是在当前日期之前还是之后,这有关系吗? - dertkw
是的。它需要在当前日期之后。 - Dylan Wheeler
当你找到正确答案时,如果它已经发布在这里,请选择它作为最佳答案;如果没有发布,请发布并将其选为最佳答案。如果你不经常这样做,人们将来就不会回答你的问题:/ - Ryan Amos
4个回答

15
您可以通过计算时间差(例如Date#getTime())并返回最小值来在线性时间内解决问题。
public static Date getNearestDate(List<Date> dates, Date currentDate) {
  long minDiff = -1, currentTime = currentDate.getTime();
  Date minDate = null;
  for (Date date : dates) {
    long diff = Math.abs(currentTime - date.getTime());
    if ((minDiff == -1) || (diff < minDiff)) {
      minDiff = diff;
      minDate = date;
    }
  }
  return minDate;
}

[编辑]

微小的性能优化。


1
为什么要使用Long而不是long?将minDiff设置为-1并将其声明为long类型。Long比long效率低得多,因为它是一个包装器。 - Ryan Amos
@Java-Coder:这只是个想法,你肯定可以在这里解决细节问题,对吧? - maerics
@Ryan:再次演示一下算法,应该具有最佳的大O性能。更小的性能细节可以由有能力的程序员解决... - maerics
@Java-Coder:你修改了我的函数来检查空值吗?如果没有,而你将一个空值传递给它,它会愉快地为你取消引用... - maerics
好的,我会继续尝试。我已经在你的代码中添加了一个if语句来检查(!dates.isEmpty() && currentDate != null),然后执行for循环语句,但仍然导致NPE。有什么建议吗? - Dylan Wheeler
显示剩余5条评论

3
使用 Date#getTime 并减去这些值。最小的结果将是您最接近的日期。

请您能否给我一个例子? - Dylan Wheeler
最高效算法的最佳通用描述,不要陷入细节。 - maerics

2

按日期顺序排序列表并执行二分搜索。请记住,要比较日期,可以使用Date.getTime()将日期转换为毫秒数,这通常更容易进行比较。


请问您能否展示一些通用代码的例子吗?抱歉,我是新手。 - Dylan Wheeler
2
我不会替你完成工作/作业。如果你对自己的代码有困难,请将其张贴出来,我(以及其他很多人)会指出如何改进它。顺便说一下,互联网上充满了“通用”的二分搜索示例。 - SJuan76
谷歌搜索“二项式搜索”并没有返回很多结果。而且,为什么要进行排序呢?不如直接遍历日期列表,计算每个日期与目标日期之间的差值,并取最小值即可,无需排序。 - Ray Toal
@Ray Toal:我的错,应该是“二分查找”。当然,你的方法也是有效的。只是有时候很难判断提问者的技能水平,我试图用最少的计算机科学知识来解决问题。我想我高估了我的受众。 - SJuan76
1
请查看我在帖子上的评论,以了解二分搜索的解释。我认为在这种情况下,二分搜索并不像对于确切答案不一定在数组中的情况那样有用。无论如何,当你需要重新排列时,效率就会降低,而且永远无法突破O(nlog(n))的限制。编辑:看起来已经有人说过这个了>> - Ryan Amos
显示剩余2条评论

0

你需要按最接近的日期排序。

将开始日期设置为0:

long ret = 0;

现在,你需要循环遍历列表,并保持最接近你所需日期的日期。

for(Date d : dates){
    if(Math.abs(curDate.getTime() - ret) > Math.abs(curDate.getTime() - d.getTime())){
        ret = d.getTime();
    }
}
return new Date(ret);

if语句通过比较毫秒时间来检查哪个日期更接近。使用Math.abs,可以消除方向(之前或之后)。


谢谢,我会尝试并很快让您知道我进展如何!=D - Dylan Wheeler
OP不想要最小绝对差。OP说列表中的日期必须在当前日期之后。 - Ray Toal
由于我只想要当前日期之后的日期,那么我只需要删除绝对值部分吗? - Dylan Wheeler
@Ryan s/binomial/binary/g :-) - Ray Toal
@Ray Oops :P 二进制二项式式... 没什么区别 :D(直到我上数学课!) - Ryan Amos
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接