你能用二进制搜索来使用ta jodatime DateTime List吗?

时间:2014-03-23 04:55:02

标签: java jodatime

我有一个假日对象列表,其中包含一个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)

2 个答案:

答案 0 :(得分:3)

JodaTime DateTime类实现了Comparable接口本身,因此您不需要实现Comparator

相反,只使用Collections.binarySearch只有两个参数:listkey

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)