Was ist der Unterschied zwischen der Verwendung eines Prädikats oder einer Funktion als Java-Stream-Filter?

9

Unter der Annahme, dass ich einen zufälligen Filter in einem Stream verwende, besteht die einfachste Möglichkeit darin, das Prädikat direkt einzugeben:

%Vor%

Ich kann auch einfach eine Referenz erstellen und das Prädikat im Voraus definieren:

%Vor%

Aber ich kann auch eine Funktion verwenden:

%Vor%

Soweit ich das beurteilen kann, ist das Prädikat natürlich viel begrenzter, während die Funktion Nebenwirkungen haben könnte. Aber da Leute wie Venkat Subramaniam die letztere Lösung verwenden, frage ich mich wirklich: Was sind die Hauptunterschiede hier?

    
AdHominem 22.04.2016, 16:16
quelle

2 Antworten

12

Nein! Prädikat ist im Vergleich zu einer Methodenreferenz nicht wirklich begrenzt! In der Tat sind diese Dinge alle gleich!

Sehen Sie sich die Funktionssignatur filter() an: filter(Predicate<? super T> predicate)

Und lassen Sie uns Ihre Beispiele betrachten:

x.stream().filter(e -> e % 2 == 0)

%Vor%

Der erste ist nur eine Inline-Version des letzteren.

%Vor%

und hier können Sie Method References in Aktion sehen. MR sind nur ein syntaktischer Zucker, mit dem Sie Lambda Expression basierend auf bereits existierenden Funktionen definieren können.

Am Ende des Tages werden alle diese Ausdrücke zur gleichen Implementierung der Predicate-Funktionsschnittstelle.

Sie können in Ihren Lambda Expressions auch Nebenwirkungen mit der Block-Syntax auf der rechten Seite ausführen, aber es wird generell nicht empfohlen:

%Vor%     
Grzegorz Piwowarek 22.04.2016, 16:36
quelle
4

Beim Betrachten einer Bibliothek wiederverwendbarer Prädikate ist eine Bibliothek von Funktionen, die einen booleschen Wert zurückgeben, eine weitaus vielseitigere Sammlung von Prädikaten als eine Bibliothek von statischen letzten Prädikat-Instanzen. Warum?

Betrachten Sie eine Bibliothek, die Folgendes enthält:

%Vor%

gegen

%Vor%
  • Wenn Bibliotheksfunktionen gut benannt sind, lesen sie besser. Wenn Code nach langer Abwesenheit erneut aufgerufen wird, ist es einfacher, filter(MyLib::isEven) als filter(i -> i % 2 == 0) zu scannen und filter(MyLib::isEven) sagt Ihnen genau, was aufgerufen wird, während filter(MyLib.IS_EVEN) nicht
  • ist
  • Wenn Sie nur Ihre Bibliotheksfunktion aufrufen möchten, anstatt sie als Prädikat zu verwenden, ist sie besser lesbar. MyLib.isEven(i) scannt besser als MyLib.IS_EVEN.test(i)
  • Wenn Sie IntPredicate anstelle von Predicate<Integer> a Guava Predicate<Integer> , Apache Collections4 Predicate<Integer> usw. verwenden müssen, machen Sie mit einer Bibliotheksfunktion einfach weiter MyLib::isEven . Bei einer static final Predicate<Integer> -Instanz müssten Sie sie konvertieren, indem Sie MyLib.IS_EVEN::test ausführen (und am Ende verwenden Sie trotzdem eine Methodenreferenz)

Dasselbe gilt für alle funktionalen Typen. Funktionen schreiben. Sie können mit einer einfachen Methodenreferenz auf jeden Funktionstyp angewendet werden, der der Signatur entspricht.

    
Hank D 22.04.2016 22:11
quelle

Tags und Links