#java #lambda #final
#java #лямбда-выражение #Финал
Вопрос:
Я пытаюсь просто определить время функции, используя выполняемый интерфейс, чтобы обернуть вокруг любой функции, которая мне нужна.
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;
}
}
Я требую, чтобы функция B принимала параметр, потому что я хочу проверить его сложность / big-O. Я обеспокоен тем, что я неправильно кодирую / использую лямбда-выражения. Если кто-то может помочь решить эту проблему или найти другое решение, это было бы оценено.
В качестве примечания, я знаю, что мне не нужно делать это настолько сложным с помощью управляемого интерфейса, я могу просто правильно рассчитать время в цикле while. Однако я просто хотел посмотреть, возможно ли это сделать, чтобы я мог просто ввести некоторую функцию для тестирования и в качестве синтаксического сахара.
Ответ №1:
Вы можете просто скопировать значение переменной в отдельную конечную переменную следующим образом:
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;
}
}
Ответ №2:
Попробуйте это.
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
.
Комментарии:
1. Попробуйте … добавление объяснения?
2. Спасибо за помощь! Я предполагаю, что это связано с тем, что массив является окончательным, но фактическое содержимое является гибким?