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
.
我正在尝试通过使用 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
.