假设我有以下代码:
var output = chain(
0,
n -> n + "hi",
n -> n,
n -> n + 1,
n -> n.equals("0hi1")
);
如何使该方法接受任意数量的函数?
我知道我能做到:
public static <A, B, C, D, E> E chain(
A val,
Function<? super A, ? extends B> f1,
Function<? super B, ? extends C> f2,
Function<? super C, ? extends D> f3,
Function<? super D, ? extends E> f4
) {
return f4.apply(f3.apply(f2.apply(f1.apply(val))));
}
但这严重限制了输入量。
我可以编写一些递归函数吗?也许可以接受可变参数?
类似这样的事情:
public static OutputType chain(
InputType val,
Function<?, ?>... functions
) {
var nextInput = functions[0].apply(val);
if (functions.length == 1) return nextInput;
var tail = Arrays.copyOfRange(functions, 1, functions.length);
return chain(nextInput, tail);
}
我知道我可以创建一个 monad,或者使用流,或者使用可选的链式转换:
var output = Optional
.of(0)
.map(n -> n + "hi")
.map(n -> n)
.map(n -> n + 1)
.map(n -> n.equals("0hi1"))
.get();
但我特别不想这样做。我想实现第一个代码块中可见的样式。
最佳答案
假设调用中的所有函数都具有相同的类型,那么可以在方法上使用简单的泛型类型来完成:
public static <T> T chain(
T val,
Function<T, T>... functions
) {
if (functions.length == 0) return val;
var nextInput = functions[0].apply(val);
if (functions.length == 1) return nextInput;
var tail = Arrays.copyOfRange(functions, 1, functions.length);
return chain(nextInput, tail);
}
还可以进行其他改进(例如,仅使用索引计数器进行递归以避免数组复制,或者不进行递归)。要格外小心边界条件,例如传递一个空调用。
使用此功能,您可以使用任何类型的输入,并且这些函数将需要在相同的输入和输出类型上进行操作。
关于java - 是否可以递归链接通用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77061671/