Sven Ruppert

Java 8 Streams

ISBN: 978-3-86802-498-2

© 2013 entwickler.press

Ein Imprint der Software & Support Media GmbH

Java 8 – Streams

Seit Java 8 gibt es das Streams-API. Was aber bringt es für den Entwickler? Wie wird es verwendet? Wir werden uns nun Schritt für Schritt diesem API nähern. Alle Beispiele und Quelltexte zu diesem shortcut finden sie unter: https://bitbucket.org/rapidpm/entwicklerpress-shortcut-jdk8-streams.

1 Data in – Data out

1.1 Was waren nochmal diese Streams?

Jeder ist in Java schon einmal mit irgendeiner Form von Streams konfrontiert worden. Aber was genau macht einen Stream nun im JDK 8 aus?

Streams sind keine Datenstruktur, was so viel bedeutet, dass sie keinen Storage für Daten darstellen. Es handelt sich eher um eine Pipeline für Datenströme. In dieser Pipeline werden verschiedene Transformationen auf die Daten angewendet. In diesem speziellen Fall werden die Transformationen nicht auf den Daten der Quellstruktur selbst durchgeführt. Die zugrunde liegenden Datenstrukturen wie Arrays oder Listen werden also nicht verändert. Ein Stream wrappt also die Datenstruktur, entnimmt ihr die Quelldaten und arbeitet auf Kopien.

Streams sind für den Einsatz von Lambdas konzipiert worden. Es gibt also keine Streams ohne Lambdas, was kein Problem darstellt, da Streams und Lambdas zusammen im JDK 8 enthalten sind.

Streams bieten keinen wahlfreien Zugriff per Index oder Ähnliches auf die Quelldaten. Der Zugriff auf das erste Element ist möglich, nicht jedoch auf beliebige nachfolgende Elemente.

Streams bieten guten Support, um die Ergebnisse selbst wieder als z. B. Array oder List zur Verfügung zu stellen.

Streams sind lazy organisiert. Das bedeutet, dass die Elemente erst geholt werden, wenn die Operation auf ihnen angewendet werden soll. Besteht die Datenquelle aus 1 000 Elementen, dann dauert der erste Zugriff nicht 1 000 Zeiteinheiten, sondern eine Zeiteinheit (vorausgesetzt, der Zugriff auf ein Element ist linear im Zeitverbrauch).

Streams sind parallel, wenn gewünscht. Die Streams kann man prinzipiell in zwei Hauptgruppen unterteilen: in serielle und parallele Implementierungen. Wenn also Operationen atomar und ohne Invarianten durchgeführt werden können, wird kein typischer multi-threaded Code notwendig, um die im System schlafenden Cores zu verwenden.

Streams sind ungebunden, da sie nicht wie Collections initial befüllt werden. Damit sind Streams auch unendlich. Es können Generatorfunktionen angegeben werden, die für die permanente Lieferung von Quelldaten sorgen, die erzeugt werden, wenn der Client Elemente des Streams konsumiert.

1.2 Wo kommen all die Quelldaten her?

Wenn man daran denkt, dass Streams nicht wie Collections ihre eigenen Daten halten, dann stellt sich die Frage, wo sie dann herkommen. Die gebräuchlichste Art, Streams zu erzeugen, ist die Verwendung der Methoden, um aus einer festen Anzahl von Elementen einen Stream zu erzeugen. Das sind dementsprechend die Methoden Stream.of(val1,val2,val3…), Stream.of(array) und list.stream(). Zu den Methoden aus dem Bereich der Erzeugung aus einem festen Wertevorrat gehört auch die Methode, die aus einem String einen Stream erzeugt. Ein String ist nichts anderes als eine endliche Kette von chars. Sie kann als Wertevorrat übergeben werden.

final Stream<String> splitOf = Stream.of("A,B,C".split(","));

Genauso können Streams aus Streams erzeugt werden, was in dem nächsten Artikel genauer dargestellt werden wird.

Nun fehlen noch zwei Möglichkeiten, Streams zu erzeugen. Mit einem Builder kann ein Stream programmatisch erzeugt werden.

final Stream<Pair> stream

= Stream.<Pair>builder().add(new Pair()).build();

Die letzte der Möglichkeiten, einen Stream zu erzeugen, besteht darin, einen Generator zu verwenden. Das erfolgt über die Methode Streams.generate(..) (Listing 1.1), in deren Argument die Methode eine Instanz der Klasse Supplier<T> bekommt. Wo gehen all die Daten hin?

Stream.generate(() -> {
final Pair p = new Pair();
p.id = random.nextInt(100);
p.value = "Value + " + p.id;
return p;
})

Listing 1.1: „generate“-Methode

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!