I want to compose an array of functions to one function. Given multiple functions the method should return a function which is the composition of the input functions.
One way to do this is
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;
}
I'm looking to achieve the same result by first making a stream of the array of functions. But I can't figure out how to do this
public static <T> Function<T,T> composeAll2 (Function<T,T>... functions){
Function<T,T> res = Function.identity();
Arrays.stream(functions). ???
return res;
}
What code should I enter in the last method where I put question marks now?
You can make use of the Stream#reduce()
operation:
public static <T> Function<T,T> composeAll2 (Function<T,T>... functions){
return Arrays.stream(functions).reduce(Function.identity(), Function::compose);
}
Which is identical to your iterative way of composing functions.
While @Lino's answer is concise, it is unsafe and prone to stack overflow:
List<Function<Integer, Integer>> list = Collections.nCopies(10000, i -> i + 1);
System.out.println(composeAll2(list.toArray(new Function[0])).apply(0));
If you run this code, it will fail with 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)
...
To avoid this, I suggest not using streams at all and using the old for-each
loop:
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;
};
}
This version of composeAll2
will use a constant stack space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With