我想编写一个接收List l
和两个BiFunction f1, f2
的泛型方法,并返回以下表达式的结果:
(a0 + a1) * (a2 + a3) *...*(a_{n-1} + an) * an
。
此处a1,...,an
是给定列表的元素,+
表示f1
,*
表示f2
。
逻辑部分非常简单:
List<???> resF1 = new List<>(); //calculate result of f1 for each pair
for (int i = 0; i < l.size(); i += 2) {
resF1.add(f1.apply(l.get(i), l.get(i + 1)));
}
??? ans = f2.apply(resF1.get(0), resF1.get(1)); //get initial value of ans
for (int i = 2; i < resF1.size(); i++) {
ans = f2.apply(ans, resF1.get(i)); //successively evaluate from left to right
}
ans = f2.apply(ans, l.get(l.size() - 1)); //don't forget about the last term of expr
return ans;
困难的部分是选择泛型类型。
让我们开始表单方法签名
public static <F, S, T> ??? foo(List<? extends F> l, BiFunction<???, ???, ???> f1, BiFunction<???, ???, ???> f2)
假设我们的函数将有三种泛型类型,因此类型可能尽可能通用。
我想列表的类型应该是<? extends F>
,因为我们想要从中读取值,而? extends
仅用于此目的。
至于BiFunction
:因为我们将列表元素传递给它,我想前两个字段也应该是? extends F
。 ? extends
,原因与列表中的原因相同,但我们可以为? extends S
f1
和? extends T
f2
制作f1
吗?
f2
的结果类型应该等于f2
的参数类型似乎也是合乎逻辑的,因为我们将它f1
应用于? extends F
的结果}}。但是,最后一个术语包含单个元素,它有T
,正如我们之前推断的那样。
至于返回值,我猜它应该是U
或{{1}}。
那么,你会怎么写这样的方法?
答案 0 :(得分:3)
看起来你正在过度思考这个问题。由于输入和输出类型相同,因此您只需要一个类型变量(如果它们不是,那么您需要第三个BiFunction
)。
在这种情况下,您还可以使用BinaryOperator
,这基本上等同于BiFunction<T, T, T>
。结果是(复制算法):
public static <T> T dualFold(List<T> l, BinaryOperator<T> f1, BinaryOperator<T> f2) {
List<T> resF1 = new ArrayList<>(); //calculate result of f1 for each pair
for (int i = 0; i < l.size(); i += 2) {
resF1.add(f1.apply(l.get(i), l.get(i + 1)));
}
T ans = f2.apply(resF1.get(0), resF1.get(1)); //get initial value of ans
for (int i = 2; i < resF1.size(); i++) {
ans = f2.apply(ans, resF1.get(i)); //successively evaluate from left to right
}
ans = f2.apply(ans, l.get(l.size() - 1)); //don't forget about the last term of expr
return ans;
}