Advanced Java Services | Streams |
Das neue Streamkonzept ergänzt die Programmierung mit Lambdas in idealer Weise. Man kann nun nahezu jede Sammlung von Daten "streamen" und über den erhaltenen Stream aufbereiten. Einige Beispiele werden das Vorgehen verdeutlichen. Die Erweiterung bestehender Interfaces durch default-Methoden und bestehender Klassen wie Arrays durch statische stream-Methoden schafft neue interessante Möglichkeiten.
Hier ein Auszug der Tabelle Neue 1.8 Methoden in 1.7 Klassen, Interfaces etc., die diejenigen Klassen und Interfaces zeigt, die stream-Methoden aufweisen, aufgenommen sind auch die fünf statischen Erzeugermethoden aus dem 1.8 Interface Stream.
Erzeugermethoden für Streams | |||
---|---|---|---|
Package | Klasse | Methode | Exception |
java.io | BufferedReader | public Stream<String> lines() | |
java.lang | CharSequence | default IntStream chars() | |
default IntStream codePoints() | |||
java.nio.file | Files | public static Stream<Path> list(Path dir) | IOException |
public static Stream<Path> walk(Path start, int maxDepth, FileVisitOption... options) | IOException | ||
public static Stream<Path> walk(Path start, FileVisitOption... options) | IOException | ||
public static Stream<Path> find(Path start, int maxDepth, BiPredicate<Path,BasicFileAttributes> matcher, FileVisitOption... options) | IOException | ||
public static Stream<String> lines(Path path, Charset cs) | IOException | ||
public static Stream<String> lines(Path path) | IOException | ||
java.util | Arrays | public static <T> Stream<T> stream(T[] array) | |
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) | |||
public static IntStream stream(int[] array) | |||
public static IntStream stream(int[] array, int startInclusive, int endExclusive) | |||
public static LongStream stream(long[] array) | |||
public static LongStream stream(long[] array, int startInclusive, int endExclusive) | |||
public static DoubleStream stream(double[] array) | |||
public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) | |||
java.util | BitSet | public IntStream stream() | |
java.util | Collection | default Stream<E> stream() | |
default Stream<E> parallelStream() | |||
java.util | Random | public IntStream ints(long streamSize) | |
public IntStream ints() | |||
public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) | |||
public IntStream ints(int randomNumberOrigin, int randomNumberBound) | |||
public LongStream longs(long streamSize) | |||
public LongStream longs() | |||
public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) | |||
public LongStream longs(long randomNumberOrigin, long randomNumberBound) | |||
public DoubleStream doubles(long streamSize) | |||
public DoubleStream doubles() | |||
public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) | |||
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) | |||
java.util.concurrent | ThreadLocalRandom | public IntStream ints(long streamSize) | |
public IntStream ints() | |||
public IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound) | |||
public IntStream ints(int randomNumberOrigin, int randomNumberBound) | |||
public LongStream longs(long streamSize) | |||
public LongStream longs() | |||
public LongStream longs(long streamSize, long randomNumberOrigin, long randomNumberBound) | |||
public LongStream longs(long randomNumberOrigin, long randomNumberBound) | |||
public DoubleStream doubles(long streamSize) | |||
public DoubleStream doubles() | |||
public DoubleStream doubles(long streamSize, double randomNumberOrigin, double randomNumberBound) | |||
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) | |||
java.util.regex | Pattern | public Stream<String> splitAsStream(CharSequence input) | |
java.util.stream | Stream | public static <T> Stream<T> empty() | |
public static <T> Stream<T> generate(Supplier<T> s) | |||
public static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) | |||
public static <T> Stream<T> of(T... values) | |||
public static <T> Stream<T> of(T t) | |||
java.util.zip | ZipFile | public Stream<? extends ZipEntry> stream() |
Das Arbeiten mit Streams verläuft in drei Schritten, als erstes muß ein Stream erzeugt werden, praktisch kann man aus jeder Datensammlung einen Stream erzeugen. Im zweiten Schritt ruft man sogenannte intermediäre Operationen auf, die den Stream in einen neuen verändeten Stream überführen. Es gibt im Interface Stream 16 Methoden, die einen Stream in einen weiteren Stream überführen. Es sind genau diejenigen Methoden, die zu einem Stream aufgerufen werden und wieder einen Stream zurückgeben. Die letzte Operation ist dann eine terminale operation, die in irgendeiner Form Ergebnisse liefert. Im Interface Stream gibt es eine ganze Reihe von terminalen Operationen.
Terminale Operationen sind alle Methoden des Interfaces Stream, deren Returntyp void ist oder ein einziges Element liefert. In der Stream-API gibt es 17 terminale Operationen. Wichtig ist folgendes:
Es nützt auch nichts, nach intermediären Operationen den Stream Variablen zuzuweisen, denn es gibt nur einen Stream und alle intermediären Operatoren sind lazy, soll heißen, sie erfüllen ihre Aufgabe nicht sofort, sondern warten erst mal ab, tun also nichts. Terminale Operationen dagegen sind eager, denn sie müssen ein Ergebnis liefern, deshalb stoßen erst diese die Abarbeitung der intermediären Operationen an, damit sie selbst ablaufen können. Das sieht man sehr schön an der intermediären Operation peek(Consumer c). Übergibt man hier eine Konsolausgabe als Consumer, so finden diese Ausgaben erst dann statt wenn eine terminale Operation den Stream abschließt.
Das Beispiel baut aus 11 Strings einen Stream, mit distinct() werden sodann Dubletten rausgeworfen, peek() schaut sich Ergebnis an, sort() sortiert natürlich die übriggebliebenen und forEach gibt die Elemente schließlich auf die Konsole aus.
private static void distinct_peek_sorted_forEach() { StreamstringStream3 = Stream.of("56", "45", "34", "01", "12", "23", "34", "12", "01", "45", "23"); Stream interStream = stringStream3.distinct().peek(s -> System.out.print(s + "p ")).sorted(); // keine Ausgabe nach dem obigen Statement ! interStream.forEach(s -> System.out.print("[" + s + "] ")); // sondern erst jetzt }
Zur Unterschiedung erhalten die Ausgaben über peek() ein p angehängt und die Endausgaben werden in eckige Klammern gesetzt. Hier die Ausgabe:
56p 45p 34p 01p 12p 23p [01] [12] [23] [34] [45] [56]
Intermediäre Operationen in Stream | |
---|---|
Returntyp | Name der Methode und Beschreibung |
static <T> Stream<T> | concat(Stream<? extends T> a, Stream<? extends T> b) Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. |
Stream<T> | filter(Predicate<? super T> predicate) Returns a stream consisting of the elements of this stream that match the given predicate. |
Stream<T> | distinct() Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream. |
<R> Stream<R> | flatMap(Function<? super T,? extends Stream<? extends R>> mapper) Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
DoubleStream | flatMapToDouble(Function<? super T,? extends DoubleStream> mapper) Returns an DoubleStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
IntStream | flatMapToInt(Function<? super T,? extends IntStream> mapper) Returns an IntStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
LongStream | flatMapToLong(Function<? super T,? extends LongStream> mapper) Returns an LongStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
Stream<T> | limit(long maxSize) Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length. |
<R> Stream<R> | map(Function<? super T,? extends R> mapper) Returns a stream consisting of the results of applying the given function to the elements of this stream. |
DoubleStream | mapToDouble(ToDoubleFunction<? super T> mapper) Returns a DoubleStream consisting of the results of applying the given function to the elements of this stream. |
IntStream | mapToInt(ToIntFunction<? super T> mapper) Returns an IntStream consisting of the results of applying the given function to the elements of this stream. |
LongStream | mapToLong(ToLongFunction<? super T> mapper) Returns a LongStream consisting of the results of applying the given function to the elements of this stream. |
Stream<T> | peek(Consumer<? super T> action) Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. |
Stream<T> | skip(long n) Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. |
Stream<T> | sorted() Returns a stream consisting of the elements of this stream, sorted according to natural order. |
Stream<T> | sorted(Comparator<? super T> comparator) Returns a stream consisting of the elements of this stream, sorted according to the provided Comparator. |
Terminale Operationen in Stream | |
---|---|
Returntyp | Name der Methode und Beschreibung |
boolean | allMatch(Predicate<? super T> predicate) Returns whether all elements of this stream match the provided predicate. |
boolean | anyMatch(Predicate<? super T> predicate) Returns whether any elements of this stream match the provided predicate. |
<R,A> R | collect(Collector<? super T,A,R> collector) Performs a mutable reduction operation on the elements of this stream using a Collector. |
<R> R | collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) Performs a mutable reduction operation on the elements of this stream. |
long | count() Returns the count of elements in this stream. |
Optional<T> | findAny() Returns an Optional describing some element of the stream, or an empty Optional if the stream is empty. |
Optional<T> | findFirst() Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. |
void | forEach(Consumer<? super T> action) Performs an action for each element of this stream. |
void | forEachOrdered(Consumer<? super T> action) Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. |
Optional<T> | max(Comparator<? super T> comparator) Returns the maximum element of this stream according to the provided Comparator. |
Optional<T> | min(Comparator<? super T> comparator) Returns the minimum element of this stream according to the provided Comparator. |
boolean | noneMatch(Predicate<? super T> predicate) Returns whether no elements of this stream match the provided predicate. |
Optional<T> | reduce(BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any. |
T | reduce(T identity, BinaryOperator<T> accumulator) Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. |
<U> U | reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) Performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions. |
Object[] | toArray() Returns an array containing the elements of this stream. |
<A> A[] | toArray(IntFunction<A[]> generator) Returns an array containing the elements of this stream, using the provided generator function to allocate the returned array, as well as any additional arrays that might be required for a partitioned execution or for resizing. |