使用`Collections.binarySearch`签名

时间:2016-10-22 19:10:46

标签: java algorithm generics binary-search

这是我尝试实现必须遵循的二进制搜索:

static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)

但是,我想避免代码重复并将其中一个实现委托给另一个(当前,第一个到第二个)。要做到这一点,我需要摆脱通配符?并使用第二个通用类型,如下所示:

public class BinarySearch {
    public static <Q extends Comparable<? super T>, T>
    int search(List<Q> xs, T x) {
        return search(xs, x, Q::compareTo);
    }

    public static <T>
    int search(List<? extends T> xs, T x, Comparator<? super T> cmp) {
        int l = 0, r = xs.size() - 1;

        while (l <= r) {
            int mid = l + (r - l) / 2;

            if (cmp.compare(xs.get(mid), x) == 0)
                return mid;

            if (cmp.compare(xs.get(mid), x) < 0)
                r = mid - 1;
            else
                l = mid + 1;
        }

        return xs.size();
    }
}

不幸的是,这不会编译,因错误而失败:

Non-static method cannot be referenced from a static context

我该如何解决?

PS:如果您想知道为什么来自Collections的签名看起来像他们一样,这里有一个解释:How do these two generic signatures for Collections.binarySearch differ?

PPS:曾经有(现已删除的)答案,您无法通过T::compareTo来预期Comparator。好吧,我相信你可以,这是我正在实施的QuickSort工作:https://github.com/all3fox/algos-java/blob/481f2c71952bf2c7510cb93cc1af8e90016ccf3b/src/main/java/io/github/all3fox/sort/QuickSort.java

1 个答案:

答案 0 :(得分:2)

实际上我不明白为什么要使用Q:

regexp.MustCompile

将编译并看起来足够我。 它允许我做两件事:

public static <T extends Comparable<T>>
int search(List<? extends T> xs, T x) {
    return search(xs, x, T::compareTo);
}

这里非常重要的一点是,这实际上意味着(或多或少):

BinarySearch.search(new ArrayList<Timestamp>(), new Date());
BinarySearch.search(new ArrayList<Date>(), new Timestamp(0L));

现在我们清楚地看到:x需要属于Comparable类型。您的方法中没有说明这一点。相反,有一个类型Q定义,但没有参与者实际上是这种类型。因此比较器并不是严格兼容的,但它必须,因为x的compareTo方法是比较器的实现。 BTW的另一种方法是使用int search(List<? extends T> xs, final T x) { return search(xs, x, new Comparator<T>() { @Override public int compare(T o1, T o2) { return x.compareTo(o2); } }); } 作为技巧,但仍然必须将T定义为可比较。