Java лямбда-выражение с неоконечным параметром функции
Я пытаюсь просто определить время функции, используя интерфейс 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 принимала параметр, потому что я хочу проверить сложность /big-O этого. Я беспокоюсь, что я не пишу / использую лямбда-выражения правильным образом. Если кто-то может помочь решить эту проблему или найти другое решение, это будет оценено.
Как примечание, я знаю, что мне не нужно делать это настолько сложным с интерфейсом Runnable, я могу просто выполнить синхронизацию прямо в цикле while. Тем не менее, я просто хотел посмотреть, возможно ли сделать такую вещь, чтобы я мог просто ввести некоторую функцию для тестирования и как синтаксический сахар.
2 ответа
Вы можете просто скопировать значение переменной в отдельную конечную переменную следующим образом:
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;
}
}
Лямбда-выражение ссылается на свободные переменные, копируя их внутрь. Таким образом, свободные переменные не должны быть изменены (должны быть final
). Но когда вы проходите size[0]
лямбда-выражение копирует переменную массива size
, это final
,