2015-06-26 11 views
12

Ich habe eine Frage in Bezug auf Java 8. Hier ist meine Quellcode:Bewerben JDK 8 Consumer auf String

final Consumer<String> d = e -> System.out.println(e); 
final Function<String, String> upper = x -> x.toUpperCase(); 
final Function<String, String> lower = x -> x.toLowerCase(); 

new Thread(() -> d.accept(upper.apply("hello 1"))).run(); 
new Thread(() -> d.accept(lower.apply("hello 2"))).run(); 

recht gut das funktioniert und produziert folgende Ausgabe:

HELLO 1 
hello 2 

Meine Frage ist jetzt Wenn die Syntax über d.accept und upper.apply die einzig mögliche ist, oder wenn es mehr "java 8 lambda" -Stil gibt, könnten wir die letzten zwei Zeilen schreiben.

+1

Diese Lambdas sind alle ideale Kandidaten für die Verwendung von _method references_: System.out :: println, String :: toUpperCase. –

Antwort

9

Bevor etwas zu sagen über etwa Lambda-Ausdrücke oder funktionale Schnittstellen, haben wir über Ihren wirklich problematischen Fehler sprechen: Sie rufenrun()auf einem Thread! Wenn Sie einen neuen Thread starten möchten, müssen Sie start() auf der Instanz Thread aufrufen, wenn Sie den Code der Reihe nach ausführen möchten, erstellen Sie kein Thread (aber nur ein Runnable).

Das besagt, gibt es einige default Methode auf den funktionalen Schnittstellen von Java 8 zum Kombinieren von Funktionen, z. Sie können zwei Function s über Function.andThen(…) verketten, aber die verfügbaren Kombinationen sind weit davon entfernt, vollständig zu sein.

Wenn eine bestimmte Kombination von Aufgabe in der Anwendung wiederholt, können Sie prüfen, Utility-Methoden zu erstellen:

public static <T> Runnable bind(T value, Consumer<T> c) { 
    return()->c.accept(value); 
} 
public static <T,U> Consumer<U> compose(Function<U,T> f, Consumer<? super T> c) { 
    return u->c.accept(f.apply(u)); 
} 

new Thread(bind("Hello 1", compose(upper, d))).start(); 
new Thread(bind("Hello 2", compose(lower, d))).start(); 

Aber diese drei Teile aussehen wie eine Aufgabe für den Stream API:

Stream.of("Hello 1").map(upper).forEach(d); 
Stream.of("Hello 2").map(lower).forEach(d); 

Ich habe die Erstellung des neuen Thread hier verlassen, wie es nicht ist irgendeinen Vorteil sowieso.

Wenn Sie wirklich parallele Verarbeitung möchten, können Sie es auf einer Pro-Zeichen-Basis tun können:

"Hello 1".chars().parallel() 
    .map(Character::toUpperCase).forEachOrdered(c->System.out.print((char)c)); 

aber es wird immer noch nicht jeder Vorteil der Einfachheit der Aufgabe und der fixen Gemeinkosten des Gegebenen Parallelverarbeitung.

+1

In Bezug auf die parallele Verarbeitung: die Standard 'chars()' Implementierung in JDK8 ist wirklich schlecht. Unwahrscheinlich werden Sie die spürbare Beschleunigung sogar für die langen Saiten bekommen. Es ist viel besser in JDK9. –

+2

@Tagir Valeev: Ich weiß das, aber ich wollte nicht zu sehr ins Detail gehen.Selbst mit der besseren Splitting-Unterstützung von Java 9 wird die Aufgabe dieser Frage nicht von einer parallelen Ausführung profitieren. Ich bezweifle, dass es jemals einen 'String' gibt, der lang genug ist, dass eine einfache' toUpperCase'-Transformation von einer parallelen Ausführung profitieren kann. By the way, die Java 8 API hat eine Möglichkeit, diese Einschränkung zu überwinden: Verwenden Sie 'CharBuffer.wrap (string) .chars()' anstelle von 'string.chars()' ... – Holger

+0

Vielen Dank. Das hat mir sehr geholfen. Mit Thread.run hast du absolut recht. Dies war nur ein Beispiel und hat nichts mit den Lambda zu tun. –

3

Ja, es ist die einzige mögliche Syntax. Wenn Sie das Lambda verwenden, wissen Sie nicht einmal, ob es tatsächlich Lambda ist oder nur eine einfache alte Implementierung der gegebenen Schnittstelle (über anonyme Klasse oder sogar normale Klasse). Sie müssen die funktionale Schnittstelle wie jede andere Java-Schnittstelle verwenden: Rufen Sie ihre Methode explizit auf.

4

können Sie auch wie folgt schreiben:

new Thread(() -> Stream.of("hello 1").map(upper).forEach(d)).run(); 
    new Thread(() -> Stream.of("hello 1").map(lower).forEach(d)).run(); 

Oder mehr directlry:

new Thread(() -> Stream.of("hello 1").map(String::toUpperCase).forEach(System.out::println)).run(); 
    new Thread(() -> Stream.of("hello 1").map(String::toLowerCase).forEach(System.out::println)).run(); 
Verwandte Themen