我想为一个函数组合一个函数数组。给定多个函数,该方法应返回一个函数,该函数是输入函数的组合。
一种方法是
public static <T> Function<T,T> composeAll(Function<T,T>... functions){
Function<T,T> res = Function.identity();
for(Function<T,T> f : functions){
res = res.compose(f);
}
return res;
}
我希望首先制作一系列函数来实现相同的结果。但我无法弄清楚如何做到这一点
public static <T> Function<T,T> composeAll2 (Function<T,T>... functions){
Function<T,T> res = Function.identity();
Arrays.stream(functions). ???
return res;
}
我现在应该在最后一个提出问号的方法中输入什么代码?
答案 0 :(得分:6)
您可以使用Stream#reduce()
操作:
public static <T> Function<T,T> composeAll2 (Function<T,T>... functions){
return Arrays.stream(functions).reduce(Function.identity(), Function::compose);
}
这与您组成函数的迭代方式完全相同。
答案 1 :(得分:4)
虽然@ Lino的答案很简洁,但它不安全且容易出现堆栈溢出:
List<Function<Integer, Integer>> list = Collections.nCopies(10000, i -> i + 1);
System.out.println(composeAll2(list.toArray(new Function[0])).apply(0));
如果运行此代码,它将因StackOverflowError而失败:
Exception in thread "main" java.lang.StackOverflowError
at java.util.function.Function.lambda$compose$0(Function.java:68)
at java.util.function.Function.lambda$compose$0(Function.java:68)
at java.util.function.Function.lambda$compose$0(Function.java:68)
at java.util.function.Function.lambda$compose$0(Function.java:68)
at java.util.function.Function.lambda$compose$0(Function.java:68)
at java.util.function.Function.lambda$compose$0(Function.java:68)
...
为了避免这种情况,我建议不要使用流并使用旧的for-each
循环:
public static <T> Function<T,T> composeAll2(Function<T,T>... functions){
return input -> {
T res = input;
for (Function<T, T> f : functions) {
res = f.apply(res);
}
return res;
};
}
此版本的composeAll2
将使用常量堆栈空间。