在Java8中,如何将函数列表应用于值?

在Java8中,如何将函数列表应用于值?,java,java-8,Java,Java 8,假设我有一个命令代码: List<Function<T, T>> functions = ... T value = ... for (Function<T, T> function : functions) { value = function.apply(value); } List函数=。。。 T值=。。。 for(函数:函数){ 值=函数。应用(值); } 我该如何以函数式的方式写这篇文章(就像fol

假设我有一个命令代码:

    List<Function<T, T>> functions = ...
    T value = ...
    for (Function<T, T> function : functions) {
        value = function.apply(value);
    }
List函数=。。。
T值=。。。
for(函数:函数){
值=函数。应用(值);
}

我该如何以函数式的方式写这篇文章(就像fold在Scala中所做的那样)?

几小时前,一位
消费者问了这个问题。。。您可以将它们简化为单个函数并应用:

@SafeVarargs
private static <T> Function<T, T> combineF(Function<T, T>... funcs) {
    return Arrays.stream(funcs).reduce(Function.identity(), Function::andThen);
}
@SafeVarargs
私有静态函数combineF(函数…funcs){
返回Arrays.stream(funcs).reduce(Function.identity(),Function::and then);
}

以下是尤金答案的变体,只是为了好玩:

公共静态函数组合(列表函数){
返回新对象(){
函数组合器=列表->
list.size()==1?list.get(0):
list.get(0)和this.combiner.apply(list.subList(1,list.size());
}.combiner.apply(函数);
}
这将创建一个具有递归lambda属性的匿名内部类。该属性名为
combiner
,是一个高阶函数,它将函数列表作为参数,并返回一个函数作为结果。如果列表仅包含一个元素,则此高阶函数返回列表的第一个函数,或者将
应用于列表的第一个函数,该函数是递归调用高阶函数的结果,子函数列表以第二个元素开头

需要匿名内部类,因为递归lambda只能定义为类的属性


不用说,这比使用
函数::和
二进制运算符对列表进行流式处理和缩减要复杂得多。此外,递归lambda不是免费的:它们使用堆栈进行递归调用。

您可以将值和
#forEach
设置为
函数
列表,但这并不能真正为您带来任何好处(而且也不能真正发挥作用)。总的来说,代码看起来很好,java是一种命令式语言。这将有助于……foreach的问题是,他们需要更新共享状态。我需要的是将一个函数的结果传递给链中的下一个函数。虽然语义相同,
.reduce(function::and then)。orElse(function.identity())
可能会生成一个稍微更有效的函数。@srborlongan前面已经讨论过,请参阅:
reduce(function.identity(),function::and)
将使用identity函数作为起点,并为每个函数调用
,生成identity函数和下一个函数的组合函数(除非identity覆盖
,这在当前JRE中不存在)。相反,
reduce(Function::and then)
将返回单个元素流的唯一函数,并且仅调用
and
,如果有多个函数,并且仅当流为空时才使用
标识(),但是也不需要保存,因为创建
供应商
并不比调用
函数.identity()
便宜。如果这种情况在代码中的不同位置多次发生,最终结果将是
orElse(Function.identity())
将比
orElseGet(Function::identity)
便宜。另见@Didier L:你指的是哪一个?传递给
orElseGet(…)
Function::identity
等临时实例可能会被消除。当与其他函数组合
Function.identity()
时,JVM在评估时可能会内联它们的代码路径(尽管如果有多个函数,它可能会达到阈值),因此CPU性能可能是相同的,但只要函数被引用,组合函数的较高内存消耗就可能一直存在……除了为lambda创建要递归的字段外,Java 8中另一种(不太直观的)方法是使用@srborlongan或。。。
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);
}