是否可以在方法定义中使用普通的 BiFunction
Is this possible to do using plain BiFunction in method definition
我遇到了以下问题:一个方法应该接受一个双函数,它有两个参数——一个是 Collection<T>
类型,另一个是 T
类型;实际函数实际上可能是 Collection::remove
或 Collection::add
,或更复杂的操作;实际函数用于十几个集合,函数中有几种类型的值和集合。
最初没有通用性——只有 Collection<String>
,元素是 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());
}
但失败了——我可能只是在一个地方或另一个地方遇到编译错误,无论我使用什么类型参数都会失败。
我的一个尝试是
<T> void visitElement(Element e,
BiFunction<Collection<T>, T, Boolean> elementOp)
不会在传入 Collection::add
时失败,而是在实际将函数应用于 Collection<String>
和 String
时失败;或 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 Mars Java 编译器,所以这可能只是因为那里有一些错误而无法工作。
您不能将 BiFunction
与 T
泛型一起使用来处理这两种情况(String
和 Integer
)。
此代码无法编译:
<T> void visitElement(Element e,
BiFunction<Collection<T>, T, Boolean> elementOp) {
...
elementOp.apply(idCodes, e.getIdCode());
elementOp.apply(weights, e.getWeight());
}
因为 BiFunction
是一个泛型 class 并且您使用 Collection<T>
和 T
作为函数参数对其进行了参数化。
所以你只能传Collection<T>
和T
objects/variables而你传
第一次调用 Collection<String>
和 String
,第二次调用 Collection<Integer>
和 Integer
。
有了这个自定义界面,情况就不同了:
interface ElementOp {
<T> boolean apply(Collection<T> collection, T item);
}
这行得通:
elementOp.apply(idCodes, e.getIdCode());
elementOp.apply(weights, e.getWeight());
与BiFunction
相反,它可以接受用任何class.
声明的任何变量作为参数
要保留的是 ElementOp
不是通用的 class.
T
实际上只是一个方法范围泛型,它推断所传递参数的类型。
为了满足您的要求:多次调用相同的方法(Collection.add()
或 Collection.remove()
)但使用不同类型的参数(String
或 Integer
),您不想使用通用的 BiFunction<T,Collection<T>, Boolean>
.
您介绍的自定义功能界面更适合。
嗯,你的第一次尝试没有成功,因为当你遇到这样的事情时:
<T> void visitElement(Element e, BiFunction<Collection<T>, T, Boolean> elementOp) {
// some code
}
visitElement
知道的只有 T
类型;它知道 elementOp
是 BiFunction<Collection<T>, T, Boolean>
类型; a 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);
我遇到了以下问题:一个方法应该接受一个双函数,它有两个参数——一个是 Collection<T>
类型,另一个是 T
类型;实际函数实际上可能是 Collection::remove
或 Collection::add
,或更复杂的操作;实际函数用于十几个集合,函数中有几种类型的值和集合。
最初没有通用性——只有 Collection<String>
,元素是 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());
}
但失败了——我可能只是在一个地方或另一个地方遇到编译错误,无论我使用什么类型参数都会失败。
我的一个尝试是
<T> void visitElement(Element e,
BiFunction<Collection<T>, T, Boolean> elementOp)
不会在传入 Collection::add
时失败,而是在实际将函数应用于 Collection<String>
和 String
时失败;或 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 Mars Java 编译器,所以这可能只是因为那里有一些错误而无法工作。
您不能将 BiFunction
与 T
泛型一起使用来处理这两种情况(String
和 Integer
)。
此代码无法编译:
<T> void visitElement(Element e,
BiFunction<Collection<T>, T, Boolean> elementOp) {
...
elementOp.apply(idCodes, e.getIdCode());
elementOp.apply(weights, e.getWeight());
}
因为 BiFunction
是一个泛型 class 并且您使用 Collection<T>
和 T
作为函数参数对其进行了参数化。
所以你只能传Collection<T>
和T
objects/variables而你传
第一次调用 Collection<String>
和 String
,第二次调用 Collection<Integer>
和 Integer
。
有了这个自定义界面,情况就不同了:
interface ElementOp {
<T> boolean apply(Collection<T> collection, T item);
}
这行得通:
elementOp.apply(idCodes, e.getIdCode());
elementOp.apply(weights, e.getWeight());
与BiFunction
相反,它可以接受用任何class.
声明的任何变量作为参数
要保留的是 ElementOp
不是通用的 class.
T
实际上只是一个方法范围泛型,它推断所传递参数的类型。
为了满足您的要求:多次调用相同的方法(Collection.add()
或 Collection.remove()
)但使用不同类型的参数(String
或 Integer
),您不想使用通用的 BiFunction<T,Collection<T>, Boolean>
.
您介绍的自定义功能界面更适合。
嗯,你的第一次尝试没有成功,因为当你遇到这样的事情时:
<T> void visitElement(Element e, BiFunction<Collection<T>, T, Boolean> elementOp) {
// some code
}
visitElement
知道的只有 T
类型;它知道 elementOp
是 BiFunction<Collection<T>, T, Boolean>
类型; a 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);