如何编写接收列表和两个BiFunction并计算表达式的泛型方法?

时间:2018-02-03 14:17:28

标签: java generics java-8

我想编写一个接收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}}。

那么,你会怎么写这样的方法?

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