2016-10-24 2 views
2

Ich möchte Lambda-Ausdruck durch Methode Referenz im folgenden Beispiel ersetzen:Methode Referenz vs Lambda-Ausdruck

public class Example { 

     public static void main(String[] args) { 
      List<String> words = Arrays.asList("toto.", "titi.", "other"); 
     //lambda expression in the filter (predicate) 
      words.stream().filter(s -> s.endsWith(".")).forEach(System.out::println); 
     } 
    } 

Ich möchte ein, so etwas schreiben:

words.stream().filter(s::endsWith(".")).forEach(System.out::println); 

ist es möglich, zu transformieren beliebiger Lambda-Ausdruck zur Methodenreferenz.

+0

Mögliche Duplikate von [Methodenreferenzen für nicht leere Argumente?] (Http://StackOverflow.com/questions/15667804/method-references-for-non-empty-arguments) – fafl

+0

Vielen Dank für Ihre Antwort. kannst du mir bitte eine transformation in meinem fall zeigen weil ich mit (s :: endsWith (".")) einen kompilierungsfehler bekomme. – midy62

+5

Sie können '' 'nicht verwenden, wenn sich das Argument im Instanzaufruf befindet. Sie können 's ->" hi ".equals (s)' mit '" hi ":: equals ersetzen, aber nicht, wenn es' s -> s.equals ("hi") ' –

Antwort

3

Es gibt keine Möglichkeit „jeden Lambda-Ausdruck zu Verfahren Bezug zu transformieren“, aber Sie können eine Fabrik für einen bestimmten Zieltyp implementieren, wenn dieser wiederkehrenden Bedarf dient:

public static <A,B> Predicate<A> bind2nd(BiPredicate<A,B> p, B b) { 
    return a -> p.test(a, b); 
} 

mit diesem können Sie schreiben

words.stream().filter(bind2nd(String::endsWith, ".")).forEach(System.out::println); 

aber eigentlich gibt es keinen Vorteil. Technisch gesehen macht ein Lambda-Ausdruck genau das, was Sie wollen, es gibt den minimal notwendigen Argument-Transformationscode, ausgedrückt als den Körper des Lambda-Ausdrucks, kompiliert in eine synthetische Methode und eine Methodenreferenz auf diesen synthetischen Code. Die Syntax
s -> s.endsWith(".") ist auch schon die kleinste mögliche Syntax, um diese Absicht auszudrücken. Ich bezweifle, dass Sie ein kleineres Konstrukt finden können, das immer noch mit dem Rest der Java-Programmiersprache kompatibel ist.

+0

danke Holger, ich habe eine andere Frage bitte, – midy62

+0

warum, wenn ich verwende: Lieferant x = String :: toUpperCase; Ich bekomme "kann nicht einen statischen Verweis auf die nicht-statische Methode toUpperCase() aus dem Typ String" aber wenn ich BiPredicate verwenden x = String :: endsWith; das funktioniert gut – midy62

+2

Wie soll 'toUpperCase' ein' Lieferant' sein? Es erfordert eine "Zeichenfolge", um in Großbuchstaben zu konvertieren, so dass Sie einen Funktionstyp verwenden müssen, der eine "Zeichenfolge", z. 'Funktion ' oder 'UnaryOperator '. Oder Sie binden eine Instanz wie 'Lieferant x =" foo ":: toUpperCase', aber es gibt nicht viel Verwendung in einem Lieferanten, der immer" FOO "' liefert ... – Holger

3

Sie können selectWith() von Eclipse Collections verwenden. selectWith() dauert eine Predicate2, die 2 Parameter anstelle einer Predicate dauert. Der zweite Parameter zu selectWith() wird als der zweite Parameter an die Predicate2 jedes Mal, wenn es aufgerufen wird, einmal pro Element im iterable übergeben.

MutableList<String> words = Lists.mutable.with("toto.", "titi.", "other"); 
words.selectWith(String::endsWith, ".").each(System.out::println); 

von Eclipse-Kollektionen ist begierig darauf, wenn Sie Sie lazily dann asLazy()

words.asLazy().selectWith(String::endsWith, ".").each(System.out::println); 

verwenden können, um iterieren möchten Wenn Sie nicht aus List ändern können:

List<String> words = Arrays.asList("toto.", "titi.", "other"); 
ListAdapter.adapt(words).selectWith(String::endsWith, ".").each(System.out::println); 

Eclipse-Kollektionen 'RichIterable hat mehrere andere * Mit Methoden, die gut mit Methodenreferenzen arbeiten, einschließlich rejectWith(), partitionWith(), detechWith(), anySatisfyWith(), allSatisfyWith(), noneSatisfyWith(), collectWith()

Hinweis: Ich bin ein Beitrag Kollektionen Eclipse.

Verwandte Themen