2015-09-02 8 views
12

Nehmen wir an, ich möchte über eine Sammlung von Objekten iterieren.Implementierungsunterschiede/Optimierungen zwischen Lambda Expressions und anonymen Klassen

List<String> strmap = ... 
//Without lambdas 
strmap.stream().filter(new Predicate<String>() { 
     public boolean test(String string) { 
      return string.length == 10; 
     } 
}.forEach(new Consumer<String>() { 
     public void accept (String string) { 
      System.out.println("string " + string + " contains exactly 10 characters"); 
     } 
} 
//With lambdas 
strmap.stream() 
     .filter(s -> s.length == 10) 
     .forEach(s -> System.out.println("string " + s + " contains exactly 10 characters"); 

Wie funktioniert das zweite Beispiel (ohne lambdas)? Ein neues Objekt (Predicate und Consumer) wird jedes Mal erstellt, wenn ich den Code aufruft. Wie viel kann der Java Jit Compiler einen Lambda-Ausdruck optimieren? Für eine bessere Leistung sollte ich alle Lambdas als Variable deklarieren und immer nur eine Referenz übergeben?

private Predicate<String> length10 = s -> s.length == 10; 
private Consumer<String> printer = s -> { "string " + s + " contains exactly 10 characters"; } 

strmap.stream() 
     .filter(length10) 
     .forEach(printer); 
+3

Siehe [hier] (http://stackoverflow.com/q/27524445/2711488). Und [dies] (http://stackoverflow.com/a/23991339/2711488) gilt auch für Lambda-Ausdrücke sowie Methodenreferenzen. HotSpot kann die temporären Instanzen von inneren Klassen optimieren, aber für statusfreie Lambda-Ausdrücke gibt es zunächst keine temporären Instanzen. – Holger

+1

@Holger - nette Antworten – ZhongYu

Antwort

6

Wie das zweite Beispiel (ohne Lambda-Ausdrücke) arbeiten? Ein neues Objekt (Predicate und Consumer) wird jedes Mal erstellt, wenn ich den Code aufruft. Wie viel kann der Java Jit Compiler einen Lambda-Ausdruck optimieren? Für eine bessere Leistung sollte ich alle Lambdas als Variable deklarieren und immer nur eine Referenz übergeben?

Die Aufgabe des JIT besteht darin, es so zu machen, dass Sie sich keine Sorgen darüber machen müssen. Zum Beispiel kann das JIT (und ich glaube, es wird es machen) so beschaffen sein, dass s -> s.length == 10 automatisch zu einer statischen Konstante wird, so dass es in der gesamten Klasse wiederverwendet wird, nicht nur in dieser Instanz. Es könnte sogar für andere Klassen wiederverwendet werden, die das gleiche Lambda woanders verwenden.

Der ganze Punkt von Lambdas ist, dass Sie einfach den einfachsten Code schreiben sollten, der Sinn macht, und das JIT hat die Freiheit zu tun, was auch immer es braucht, um das effizient zu machen. Aus diesem Grund werden Lambdas mit invokedynamic erzeugt, anstatt an anonyme innere Klassen zu entschuldigen.

Schreiben Sie den einfachen Code; Vertrauen Sie der JIT, das Richtige zu tun. Dafür ist es da. Das heißt, wenn Sie die überwältigenden, komplizierten nitty-ritty Details wollen, ist this fast sicher die beste Quelle.

+3

Da 's -> s.length() == 10' invariant ist, wird es immer zu einer Konstante, ohne dass die JIT-Hilfe benötigt wird. [This] (http://stackoverflow.com/q/27524445/2711488) gilt sogar für den interpretierten Modus ... – Holger

+0

Ich lese durch das verknüpfte Dokument, das die Implementierung angibt. AFAICT, 's -> s.length() == 10 'wird auf eine private statische Methode reduziert, aber ich habe immer noch den Eindruck, dass der JIT den Lambda-Metafaktor implementiert, der entscheidet, wie dieser in die Interface-Instanz konvertiert wird? –

+2

Nein, die [LambdaMetafactory'] (http://docs.oracle.com/javase/8/docs/api/?java/lang/invoke/LambdaMetafactory.html) ist eine gewöhnliche Java-Klasse, die Bytecode unter Verwendung der Quelle erzeugt bekannte ASM-Bibliothek. Sie können sogar einen Java-Debugger durchlaufen, wenn ein Lambda-Ausdruck das erste Mal instanziiert wird. Aufgrund der Funktionsweise der Anweisung 'invokedynamic' wird bei nachfolgenden Ausführungen jedoch das Ergebnis dieses ersten Aufrufs verwendet, bei dem es sich entweder um ein Handle für eine Konstante oder um einen Aufruf einer Factory-Methode/eines Konstruktors handelt. – Holger

Verwandte Themen