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,

Другие вопросы по тегам