Java 带有非最终函数参数的 Lambda 表达式

Java Lambda Expression with Non-final Function Paramter

我正在尝试通过使用 Runnable 接口环绕我需要的任何函数来简单地为函数计时。

private static double time(Runnable runnable) { // returns how long runnable took
    long startTime = System.nanoTime();
    runnable.run();
    return (System.nanoTime() - startTime) / 1000000000.0;
}

然后我可以简单地执行以下操作:

double durationOfFunctionA = time(Driver::functionA); // functionA belongs in class Driver

但是,如果我有一个带参数的函数,则必须修改为:

double durationOfFunctionB = time(() -> functionB(someParameter));

我遇到的问题是 'someParameter' 必须是最终的或实际上是最终的。这个问题有什么解决方法吗?我见过 forEach 循环,但我需要此参数从 1、10、100 开始呈指数增长 -> 直到满足条件。代码是这样的:

public static void main(String[] args) {
    double timer = 0;
    int size = 1;

    while(timer <= 10) {
        timer = time(() -> functionB(size));
        size *= 10;
    }
}

我要求 functionB 接受一个参数,因为我想测试它的 complexity/big-O。我担心我不是 coding/using lambda 表达式的正确方法。如果有人可以帮助解决这个问题或找到其他解决方案,将不胜感激。

附带说明一下,我知道我不必使用 Runnable 接口将其弄得如此复杂,我可以直接在 while 循环中进行计时。然而,我只是想看看是否有可能做这样的事情,这样我就可以输入一些函数来测试,并作为语法糖。

您可以像这样简单地将变量值复制到单独的最终变量:

double timer = 0;
int size = 0;
while(true) {
  final finalSize = size;
  timer = time(() -> functionB(finalSize));
  size *= 10;
}

另外,我可以建议你为你想要计时的函数做一些更多的计时函数,用于不同数量的参数。 在这里你可以怎么做:

public class Test {

    public static void main(final String[] args) {
        int ttt = 0;
        time(ttt, Test::func);
        time(ttt, ttt, Test::func);
    }

    public static void func(int i) {

    }

    public static void func(int i, int j) {

    }

    public static <T> double time(T arg, Consumer<T> func) {
        long startTime = System.nanoTime();
        func.accept(arg);
        return (System.nanoTime() - startTime) / 1000000000.0;
    }

    public static <T1, T2> double time(T1 arg1, T2 arg2, BiConsumer<T1, T2> func) {
        long startTime = System.nanoTime();
        func.accept(arg1, arg2);
        return (System.nanoTime() - startTime) / 1000000000.0;
    }

}

试试这个。

public static void main(String[] args) {
    double timer = 0;
    final int[] size = {1};

    while(timer <= 10) {
        timer = time(() -> functionB(size[0]));
        size[0] *= 10;
    }
}

Lambda 表达式通过复制内部变量来引用自由变量。 所以不能更改自由变量(必须是 final)。 但是当你传递 size[0] 时,lambda 表达式会复制数组变量 size。 是final.