Was ist ein Supplier?
Versetzte Abfrage einer Methodenausführung
Das Beispiel demonstriert die zeitlich versetzte
Methodenausführung anhand eines LocalTime
-Objektes.
import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.function.Supplier; public class SupplierBsp { public static void main(String[] args) { printTime(); } private static void printTime() { DateTimeFormatter f = DateTimeFormatter.ofPattern("HH:mm:ss"); LocalTime jetzt = LocalTime.now(); Supplier<LocalTime> jetztSuppl = LocalTime::now; System.out.println(jetzt.format(f)); // 20:46:12 System.out.println(jetztSuppl.get().format(f)); // 20:46:12 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(jetzt.format(f)); // 20:46:12 System.out.println(jetztSuppl.get().format(f)); // 20:46:15 } }
In Zeile [9] wird ein LocalTime
-Objekt
erzeugt und über dessen statische Methode now()
der momentane Zeitpunkt erfasst. Das Ergebnis wird in
einer Variablen jetzt
vom Typ LocalTime
gespeichert. Das gleiche geschieht anschließend in
Zeile [10] mit dem Unterschied, dass die Speicherung in
einer Variablen vom Typ Supplier
erfolgt.
Die darauf erfolgende Ausgabe beider Variablen zeigt
selbstverständlich identische Ergebnisse [11, 12].
Nach Pausieren des ausführenden Threads wird der
Inhalt beider Variablen erneut abgefragt und ausgegeben.
Im Unterschied zur Ausgabe von jetzt
in
Zeile [18], die das selbe Ergebnis wie in Zeile [15]
erzeugt, zeigt der vom Supplier
gelieferte
Zeitstempel, dass dieser offensichtlich erst nach
Pausieren des Threads erzeugt wurde und nicht zum
Zeitpunkt der Initialisierung des Supplier
in Zeile [14]. Dies zeigt, dass die Methode LocalTime.now()
erst zum Zeitpunkt seiner Ausgabe ausgeführt wird.
[19].
Bedingte Ausführung durch Übergabe an ein Optional
Die Klasse Optional
definiert einige
Methoden, die einen Supplier
als Parameter
entgegennehmen. Das Besondere daran ist, dass die
Verarbeitung des Suppliers nur dann erfolgt, wenn das Optional
leer ist.
private static void printTimeByOptional() { DateTimeFormatter f = DateTimeFormatter.ofPattern("HH:mm:ss"); LocalTime jetzt = LocalTime.now(); Supplier<LocalTime> jetztSuppl = LocalTime::now; Optional<LocalTime> op = Optional.of(jetzt); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Optional with DateTime: " + op.get().format(f)); // 19:53:25 System.out.println("Optional with Supplier: " + op.orElseGet(jetztSuppl).format(f)); // 19:53:25 op = Optional.empty(); // Optional leeren System.out.println("Optional is empty: " + op.isEmpty()); // true System.out.println("Empty Optional with Supplier: " + op.orElseGet(jetztSuppl).format(f)); // 19:53:28 System.out.println("Optional is empty: " + op.isEmpty()); // true }
Nach Bilden eines LocalTime
-Objektes der
aktuellen Zeit [3] und einem Supplier
mit
gleichem Inhalt [4], wird mit dem LocalTime
-Objekt
ein Optional
erzeugt [5].
Nach Pausieren
des ausführenden Threads wird der Wert des
Optionals mittels get()
ermittelt und
ausgegeben [11]. Die darauf folgende Übergabe des
Suppliers an die Optional
-Methode orElseGet()
liefert trotz des pausierten Threads das selbe Ergebnis
[12]. Dies verweist darauf, dass die Methode orElseGet()
trotz des übergebenen Suppliers den bisherigen
Inhalt des Optionals zurückgibt. Der Supplier
wird erst ausgeführt, nachdem das Optional im
nächsten Schritt geleert wurde [15].
Die letzte
Zeile der Methode zeigt schließlich, dass das Optional
auch nach Ausführung des Suppliers weiterhin leer
bleibt [16].
Mehrfachnutzung eines Streams
Ein Supplier
ermöglicht auch die
mehrfache Nutzung eines Streams. Das folgende Beispiel
demonstriert dies anhand der Ausgabe einer gefilterten List
.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class SupplierBsp {
public static void main(String[] args) {
List<String> list = List.of("Motobecane", "Brough Superior", "Indian", "Benelli", "Megola", "Scott", "Vincent", "Maico");
Stream<String> stream = filterMopeds(list);
stream.forEach(System.out::println);
System.out.println(stream.count()); // java.lang.IllegalStateException
}
private static Stream<String> filterMopeds(List<String> s) {
Stream<String> stream = s.stream().map(w -> w.toLowerCase()).filter(w -> w.startsWith("m"));
return stream;
}
}
In Zeile [8] wird eine List
mit
String-Elementen erzeugt, die an die Methode filterMopeds()
als Parameter übergeben wird. Sie erzeugt einen
Stream, der einige Elemente herausfiltert und diese
wiederum als Stream zurückgibt.
In den Zeilen
[10, 11] wird dieser Stream weiterverwendet, um die
Elemente selbst, sowie in einem weiteren Schritt deren
Anzahl auszugeben.
Das Ergebnis zeigt die Ausgabe dreier historischer
Motorradmarken gefolgt von einer IllegalStateException
.
Die Ursache liegt darin, dass ein Stream nur ein Mal
verarbeitet werden kann, sodass die Anzahl der Elemente
nicht ermittelt werden kann [11].
Arbeitet man die Methode so um, dass ein Supplier<Stream<String>>
zurückgegeben wird, kann der Stream bedenkenlos
zwei Mal nacheinander weiterverarbeitet werden:
private static Supplier<Stream<String>> filterMopedsBySuppl(List<String> s) { Supplier<Stream<String>> suppl = () -> s.stream().map(w -> w.toLowerCase()).filter(w -> w.startsWith("m")); return suppl; } //... Supplier<Stream<String>> supplStream = filterMopedsBySuppl(list); supplStream.get().forEach(System.out::println); System.out.println(supplStream.get().count()); // Ausgabe: // motobecane // megola // maico // 3
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.