© DrHitch/Shutterstock.com
Java 9 Streams

4 StreamSupport


Kommen wir nun zur Klasse StreamSupport, die uns zu den Basiselementen eines Streams führt. Die hier vorgestellten Methoden werden für die Erzeugung eigener Streams verwendet. In der API-Dokumentation wird diese Klasse als low-level bezeichnet.

Da die einzelnen Methoden im Aufbau alle gleichförmig sind, werden wir uns an dieser Stelle lediglich die Methode zur Erzeugung eines Stream<T> ansehen. Die Methoden der Klasse StreamSupport sind allesamt statisch, können also direkt aufgerufen werden und sind vom Verhalten her Factory-Methoden. Es gibt hier zwei Ausprägungen (beide in Listing 4.1):

  • Die erste Version hat zwei Parameter, eine Instanz vom Typ Spliterator und ein Boolean, um anzugeben, ob es sich um einen parallelen Stream handeln soll.
  • Die zweite Variante erwartet einen Supplier für einen Spliterator, ein int zur Angabe der Charakteristiken und ebenfalls einen Boolean zur Angabe, ob es ein paralleler Stream werden soll.
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel)

public static <T> Stream<T> stream(Supplier<? extends Spliterator<T>> supplier, int characteristics, boolean parallel)

Listing 4.1: „StreamSupport“ in JDK 9

4.1 Spliterators

Wie wir gerade gesehen haben, benötigen wir Instanzen vom Typ Spliterator. Auch hier gibt es eine Klasse, ähnlich der Klasse Collectors, die uns eine Reihe von Hilfsmethoden zur Erzeugung eines Spliterators anbietet. Diese Methoden gibt es auch zur Erzeugung der Varianten, die verwendet werden können, um einen IntStream, DoubleStream usw. zu erzeugen. Wir werden hier das Augenmerk auf die Erzeugung von regulären Streams werfen.

4.2 Klasse „Spliterators“

Kommen wir zur ersten Frage: Wozu benötigen wir diese Spliterators und was für eine Aufgabe sollen sie eigentlich übernehmen?

Die Aufgabe eines Spliterators ist recht einfach erklärt: Er soll Streams aufteilen können. Damit werden die Arbeitspakete erzeugt, die dann parallel abgearbeitet werden können. Für die Erzeugung von sequenziellen Streams werden Spliterators benötigt, die lediglich ein einziges Arbeitspaket zurückliefern. Das hier angedeutete Verfahren stammt noch von Java 7, als der ForkJoinPool eingeführt worden ist. Die Implementierungen des Streams-API basieren auf der Verwendung genau dieses Default-ForkJoinPools. Um die Aufgaben zu verteilen, werden einzelne Arbeitspakete benötigt, die unabhängig voneinander in diesem Pool abgearbeitet werden können. Unabhängig meint nicht vollständig voneinander losgelöst, können doch Arbeitspakete im Ergebnis auf den Teilergebnissen der Unterpakete beruhen. Wir werden darauf nochmals bei der Besprechung der Implementierung von Spliterators eingehen.

emptySpliterator()

Diese Methode liefert einen Spliterator<T> zur Erzeugung von sequenziellen Streams.

iterator(..)

Mithilfe der Methode Iterator<T> iterator(Spliterator<? extends T> spliterator) kann man einen Spliterator in einen Iterator transformieren. Dieser Iterator kann dann wieder wie gewohnt verwendet werden.

spliterator(Collection, characteristics)

Um einen Spliterator zu erzeugen, erwartet diese Methode die Angabe einer Collection und eines int-Werts zur Angabe der Charakteristik. Die Collection kann jede beliebige Variante sein, zum Beispiel ein ArrayList:

Spliterator<T> spliterator(Collection<? extends T> c, int characteristics)

Was hat es nun mit diesen Charakteristiken auf sich? Hier wird ein int-Wert übergeben, der eine Bitmaske repräsentiert (Listing 4.2). Um diese zu erzeugen, sollte man die dafür vorgesehenen Konstanten aus dem Interface Spliterator verwenden (Tabelle 4.1).

CONCURRENT

Zeigt an, dass die verwendete Quelle conc...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang