2017-09-16 45 views
3

我有以下問題:一個方法應在雙功能需要兩個參數 - 一個是Collection<T>型的,另一種是T;實際功能可實際上Collection::removeCollection::add,或更復雜的操作;實際功能是用於收集的十幾家和有幾種類型的功能價值和收藏。這可能使用的方法定義簡單的雙功能做

最初沒有泛型 - 有隻是Collection<String> S和要素是String這麼聲明參數作爲BiFunction<Collection<String>, String, Boolean>工作得很好:

List<String> idCodes; 
void visitElement(Element e, 
        BiFunction<Collection<String>, String, Boolean> elementOp) { 
    elementOp.apply(idCodes, e.getIdCode()); 
} 

但是後來我加入其他類型的集合也發現我再也無法找到如何使用BiFunction一般:

List<String> idCodes; 
List<Integer> weights; 

void visitElement(Element e, 
        BiFunction<...> elementOp) { 
    elementOp.apply(idCodes, e.getIdCode()); 
    elementOp.apply(weights, e.getWeight()); 
} 

但失敗 - 我可以得到一個地方或另一個編譯錯誤,不管我用什麼d的類型參數,它會失敗。

我的一個嘗試是Collection::add路過的時候,但實際應用的功能Collection<String>String

<T> void visitElement(Element e, 
         BiFunction<Collection<T>, T, Boolean> elementOp) 

會失敗不會;或Collection<Integer>int

然後我又接口:

interface ElementOp { 
    <T> boolean apply(Collection<T> collection, T item); 
} 

並沒有那麼令人驚訝的現在這個工程完全按照我想要的。所以我的問題是:

難道我真的要使用

interface ElementOp { 
    <T> boolean apply(Collection<T> collection, T item); 
} 

void visitElement(Element e, 
        ElementOp elementOp) { 
    elementOp.apply(idCodes, e.getIdCode()); 
    elementOp.apply(weights, e.getWeight()); 
} 

還是會以某種方式可以使用BiFunction這種情況?

P.S.我使用Eclipse 4.3火星Java編譯器,所以它可能只是這可能不是因爲一些bug的在那裏工作。

回答

2

您不能使用BiFunctionT generic來處理這兩種情況(StringInteger)。

此代碼不能編譯:

<T> void visitElement(Element e, 
     BiFunction<Collection<T>, T, Boolean> elementOp) { 
    ... 
    elementOp.apply(idCodes, e.getIdCode()); 
    elementOp.apply(weights, e.getWeight()); 
} 

BiFunction是一個通用類和你Collection<T>T作爲函數參數參數吧。
所以,當你通過在拳頭呼叫 Collection<String>StringCollection<Integer>Integer在第二個你只能通過Collection<T>T對象/變量。

與此自定義界面,情況就不同了:

interface ElementOp { 
    <T> boolean apply(Collection<T> collection, T item); 
} 

這工作:

elementOp.apply(idCodes, e.getIdCode()); 
elementOp.apply(weights, e.getWeight()); 

違背BiFunction它可以作爲參數接受任何類中聲明的任何變量。
要保留的東西是ElementOp不是一個泛型類。
T確實只是一個方法範圍泛型,它推斷了傳入參數類型的類型。


爲了滿足您的要求:調用多次同樣的方法(Collection.add()Collection.remove()),但不同類型(StringInteger)的指定參數時,你不希望使用一個通用的BiFunction<T,Collection<T>, Boolean>
您介紹的自定義功能界面更適合。

2

嗯,你的第一次嘗試沒有成功,因爲當你有這樣的事情:

<T> void visitElement(Element e, BiFunction<Collection<T>, T, Boolean> elementOp) { 
    // some code   
} 

所有這一切visitElement知道是T類型;它知道elementOpBiFunction<Collection<T>, T, Boolean>類型;將由編譯器推斷的T

我看不出有什麼理由在這裏介紹另一個interface,當時你可以簡單地改變一下方法。還要注意,因爲你不使用的結果無論如何,我用BiConsumer而不是BiFunction

void visitElement(T value, BiConsumer<Collection<T>, T> elementOp, Collection<T> elements) { 
     elementOp.accept(elements, value); 
} 

並使用它:

BiConsumer<Collection<String>, String> bi = Collection::remove; 

    Element e = ... 
    Collection<String> idCodes...; 
    visitElement(e.getIdCode(), bi, idCodes);