我有一个假日对象列表,其中包含一个jodatime DateTime字段。此列表从最早的日期到最晚的日期手动订购。
我想使用二进制搜索来搜索匹配项。我实现了一个比较器,但算法似乎没有朝着正确的方向发展。 jodatime DateTimes不适合二进制搜索,还是我需要做的其他事情才能使这个工作?
请注意,我正在使用Collections.binarySearch工具并遵循以下示例: http://java2novice.com/java-collections-and-util/collections/binary-search/
以下是搜索输出:
Date 1:
2015-02-16T00:00:00.000-08:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
Date 1:
2016-10-10T00:00:00.000-07:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
Date 1:
2017-03-31T00:00:00.000-07:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
Date 1:
2017-10-12T00:00:00.000-07:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
Date 1:
2017-11-23T00:00:00.000-08:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
Date 1:
2017-11-24T00:00:00.000-08:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
Date 1:
2017-12-25T00:00:00.000-08:00
Target date:
2014-12-25T00:00:00.000-08:00
no match
-71
比较
class HolidayComparator implements Comparator<Holiday> {
public int compare(Holiday h1, Holiday h2) {
System.out.println("Date 1:");
System.out.println(h1.getDate());
System.out.println("Target date:");
System.out.println(h2.getDate());
if(h1.getDate().equals(h2.getDate())) {
return 0;
}
else {
System.out.println("no match");
return -1;
}
}
};
添加其他一些类:
public static List<Holiday> getAllHolidays() {
return allHolidays;
}
假日对象:
public static class Holiday {
DateTime date;
String name;
Holiday(int i, int j, int k, String x) {
date = new DateTime (i, j, k, 0, 0);
name = x;
}
public DateTime getDate() {
return date;
}
}
列表:
private static List<Holiday> allHolidays = Arrays.asList(new Holiday(2012, 12, 25, "Christmas 2012"), etc.)
二进制搜索:
int index = Collections.binarySearch(Holidays.getAllHolidays(), new Holidays.Holiday(2014, 12, 25, null));
返回:
The method binarySearch(List<? extends Comparable<? super T>>, T) in the type Collections is not applicable for the arguments (List<Holidays.Holiday>, Holidays.Holiday)
答案 0 :(得分:3)
JodaTime DateTime
类实现了Comparable
接口本身,因此您不需要实现Comparator
。
相反,只使用Collections.binarySearch
只有两个参数:list
和key
。
Comparator
的实施可能存在错误,如果您发布,我们可能会识别出来。
但问题是,是否可以在二进制搜索中使用DateTime
,答案是:是。让内置的DateTime.compareTo
函数(在超类AbstractInstant
中实现)完成它的工作。
<强>附录强>
如您的代码所示,您不是直接比较DateTime
个对象,而是使用Holiday
比较HolidayComparator
个对象。
类Comparator
的Javadoc描述了compare
方法应返回的内容:
比较其订单的两个参数。返回一个负整数, 零或正整数,因为第一个参数小于,等于 到,或大于第二个。
如果对象相等,则您的方法仅返回0,否则返回-1。这是不正确的,它会混淆Collections.binarySearch
方法。
请改为尝试:
class HolidayComparator implements Comparator<Holiday> {
public int compare(Holiday h1, Holiday h2) {
return h1.getDate().compareTo(h2.getDate());
}
}
这是最好的方法,因为它重用了JodaTime中的现有代码,并且它不会让你依赖它的内部。为了更好,你应该添加null
的支票,如果你的假期列表中有null
值,或者你有一个null
日期Holiday
个对象。
如果你想更多地了解内部:DateTime
(超类AbstractInstant
)中的compareTo方法实际上比较了方法getMillis()
的结果,所以另一种方法是写这个是:
public int compare(Holiday h1, Holiday h2) {
long millis1 = h1.getDate().getMillis();
long millis2 = h2.getDate().getMillis();
return Long.compare(millis1, millis2);
}
Long.compare
实现为:
Long.compare
:
public static int compare(long x, long y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
答案 1 :(得分:1)
根据您更新的代码,“假日无法比较,因此您无法使用
int index = Collections.binarySearch(Holidays.getAllHolidays(), new Holidays.Holiday(2014, 12, 25, null));
相反,您将HolidayComparator
更改为使用DateTime
的内置可比性,例如......
class HolidayComparator implements Comparator<Holiday> {
public int compare(Holiday h1, Holiday h2) {
return h1.getDate().compareTo(h2.getDate());
}
};
您应该可以使用Collections.binarySearch(List<? extends T> list, T key, Comparator<? super T> c)