Here's a variant on Eugene's answer, just for fun:
public static <T> Function<T, T> combine(List<Function<T, T>> functions) {
return new Object() {
Function<List<Function<T, T>>, Function<T, T>> combiner = list ->
list.size() == 1 ? list.get(0) :
list.get(0).andThen(this.combiner.apply(list.subList(1, list.size())));
}.combiner.apply(functions);
}
This creates an anonymous inner class with an attribute that is a recursive lambda. This attribute is named combiner
and it's a higher-order function that takes a list of functions as an argument and returns a function as a result. This higher-order function returns the first function of the list if the list contains only one element, or applies andThen
to the first function of the list, with the function that results of the recursive call to the higher-order function with the sublist of functions that starts with the second element.
The anonymous inner class is needed because recursive lambdas can only be defined as attributes of a class.
Needless to say this is way more complex than streaming the list and reducing with the Function::andThen
binary operator. Besides, recursive lambdas aren't for free: they use the stack for the recursive calls.