2016-10-09 2 views
0

Ich versuche, eine Funktion einfach zu time-Zeit zu setzen, indem ich die Runnable-Schnittstelle verwende, um die von mir benötigte Funktion umzubrechen.Java-Lambda-Ausdruck mit nicht abschließenden Funktionsparametern

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

dann konnte ich einfach folgendes tun:

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

jedoch, wenn ich eine Funktion haben, die einen Parameter annimmt, muss sie geändert werden:

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

Das Problem, das ich Ich bin der Meinung, dass 'someParameter' endgültig oder effektiv sein muss. Gibt es eine Problemumgehung dieses Problem? Ich habe Schleifen mit forEach gesehen, aber ich brauche diesen Parameter exponentiell von 1, 10, 100 -> bis eine Bedingung erfüllt ist. Der Code ist dies:

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

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

I FunktionD erfordern in einem Parameter zu nehmen, weil ich die Komplexität/big-O davon testen möchte. Ich mache mir Sorgen, dass ich Lambda-Ausdrücke nicht korrekt codiere/benutze. Wenn jemand helfen kann, dieses Problem zu lösen oder eine andere Lösung zu finden, würde dies geschätzt werden.

Als eine Randnotiz, ich weiß, dass ich dies mit einer Runnable-Schnittstelle nicht so komplex machen muss, kann ich einfach das Timing direkt in der While-Schleife tun. Ich wollte jedoch nur sehen, ob es möglich ist, so etwas zu tun, also könnte ich einfach eine Funktion zum Testen eingeben und als syntaktischen Zucker.

Antwort

1

Sie können einfach den Variablenwert kopieren letzte Variable wie folgt zu trennen:

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

Außerdem kann ich Ihnen raten einige weitere Timing-Funktionen für verschiedene Menge von Parametern für Funktionen, damit Sie zu Zeit möchten. Hier ist, wie Sie es tun können:

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; 
    } 

} 
1

bereits.

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-Ausdruck bezieht sich auf die freien Variablen, indem sie innerhalb kopiert werden. Also die freien Variablen dürfen nicht geändert werden (muss final sein). Aber wenn Sie size[0] übergeben, kopiert Lambda-Ausdruck Array-Variable size. Es ist final.

+1

Probieren Sie ... eine Erklärung hinzufügen? – GhostCat

+0

Danke für die Hilfe! Ich nehme an, dies ist, weil das Array endgültig ist, aber die tatsächlichen Inhalte sind flexibel? –

Verwandte Themen