2016-10-22 68 views
3

這是我在執行二進制搜索嘗試必須跟隨器的二進制搜索:使用`Collections.binarySearch`簽名

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。好吧,我相信你能,這裏要說的是正是這麼做的快速排序的我工作的落實:https://github.com/all3fox/algos-java/blob/481f2c71952bf2c7510cb93cc1af8e90016ccf3b/src/main/java/io/github/all3fox/sort/QuickSort.java

+1

您的二分查找有更多問題。如果找不到元素,它會丟失'return'語句。 – Codo

+0

@Codo thx,已修復。那麼泛型怎麼樣? – alisianoi

回答

2

其實我也不明白爲什麼用Q:

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)); 

很重要的一點是,這實際上意味着(或多或少):

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); 
     } 
    }); 
} 

現在,我們清楚地看到:X需要爲類型可比。這在您的方法中沒有說明。相反,有一個類型Q定義,但沒有參與者實際上是這種類型。所以比較器不是完全兼容的,但它必須,因爲x的compareTo方法是比較器的實現。另一種方法是使用Comparator.naturalOrder()作爲訣竅,但仍然必須將T定義爲Comparable。

+0

我已更新我的問題與我以前的問題,以「爲什麼默認簽名是如此複雜」的鏈接,這裏是http://stackoverflow.com/questions/40195450/how-do-these-two-generic-signatures -for-collections-binarysearch-differ – alisianoi

+0

@ all3fox好的,我做了一個編輯。但仍然沒有Q ...其實我沒有看到你提到的問題中的Q. –

+0

您已將'extend Comparable '限制在返回值之前的參數列表中。你能解釋一下它有什麼不同嗎? (或指向文檔)。這只是一個簡寫,以免在參數列表中的兩個地方寫出'extends Comparable '? – alisianoi