Java 8 中的递归 lambda 表达式

2022-09-04 21:09:54

我只是想以递归方式定义一个Java 8 lambda表达式。

Lambda 常见问题解答提到,只能在(静态)字段初始化期间定义递归 lambda 表达式。

但是我在IntelliJ中得到了一个编译器错误(javac只是报告一个错误而没有消息):

java:初始值设定项中的自引用

如果我试图写这样的东西:

static UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * f.apply( i - 1);

UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * f.apply( i - 1);

我发现让它工作的一种方法是使用数组来引用lambda有效地欺骗java编译器:

import java.util.function.UnaryOperator;

public class RecursiveLambdaExample {

    public static void main(String[] args) {

        UnaryOperator<Integer>[] fac = new UnaryOperator[1];
        fac[0] = i -> i == 0 ? 1 : i * fac[0].apply( i - 1);

        UnaryOperator<Integer> factorial = fac[0];

        System.out.println(factorial.apply(5));
    }
}

定义递归 lambda 表达式是否有其他技巧?


答案 1

您可以通过完全限定以递归方式引用的字段名称来使其正常工作。此版本编译时没有任何错误:

import java.util.function.UnaryOperator;

public class RecursiveLambdaExample {

    static UnaryOperator<Integer> fac = i -> i == 0 ? 1 : i * RecursiveLambdaExample.fac.apply( i - 1);

    UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * this.f.apply( i - 1);

    public static void main(String[] args) {
        System.out.println(new RecursiveLambdaExample().f.apply(5));
        System.out.println(fac.apply(5));
    }
}

相关:为什么 Java 8 中的 lambda 不允许对成员变量的前向引用,而匿名类则不允许?


答案 2

您可以使用嵌套类实现此目的:

public class Main {

    public static void main(String[] args) {

        class Helper {
            final UnaryOperator<Integer> f = i -> i == 0 ? 1 : i * this.f.apply( i - 1);
        }

       System.out.println(new Helper().f.apply(3));
    }
}

输出:

6

推荐