2017-09-16 14 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);