Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Stream Gatherers - Schreibe deine eigenen Strea...

Stream Gatherers - Schreibe deine eigenen Stream-Operationen!

Die Java-Stream-API wurde mit Java 8 im März 2014 veröffentlicht und hat uns ein unverzichtbares Werkzeug an die Hand gegeben, um Daten zu verarbeiten.

Doch der begrenzte Satz an intermediären Operationen – `filter`, `map`, `flatMap`, `mapMulti`, `distinct`, `sorted`, `peak`, `limit`, `skip`, `takeWhile` und `dropWhile` – führt dazu, dass komplexere Datentransformationen durch die Stream-API nicht ausgedrückt werden können.

Es fehlen z. B. Operationen wie `window` und `fold` und zahlreiche mehr, wenn man sich die Feature-Requests der Community ansieht.

Anstatt nun all diese Operationen ins Stream-Interface zu integrieren, entwickelte das JDK-Team eine neue API, die zum einen im JDK selbst genutzt wird, um heiß begehrte intermediäre Operationen bereitzustellen, und mit der zum anderen Entwicklerinnen und Entwickler ihre eigenen Operationen implementieren können.

Diese neue API heißt „Stream Gatherers“ und wurde in Java 22 im März 2024, also genau zehn Jahre nach der Einführung der Stream-API, zum ersten mal als Preview-Feature (JEP 461) veröffentlicht. In Java 23 wurde die neue API ohne Änderungen in eine zweite Preview-Runde geschickt (JEP 473), und in Java 24 wurde sie – wieder ohne Änderungen – finalisiert (JEP 485).

In diesem Talk erfahrt ihr in Theorie und Praxis (inklusive Live-Coding), was Stream Gatherers sind und wie sie funktionieren, welche Gatherer im JDK bereits verfügbar sind und wie ihr sie effektiv einsetzt, wie ihr selbst eigene Gatherer implementieren könnt und wo die Grenzen der neuen API liegen.

Avatar for Sven Woltmann

Sven Woltmann

March 31, 2025
Tweet

More Decks by Sven Woltmann

Other Decks in Programming

Transcript

  1. Copyright © 2025, HappyCoders.eu Stream-Pipeline Quelle (source) Intermediäre Operationen (intermediate

    operations) stream() Terminale Operation (terminal operation) toList() filter(…) limit(…) map(…)
  2. Copyright © 2025, HappyCoders.eu List<String> fruits = List.of("avocado", "banana", "cantaloupe",

    "dragon fruit", "fig", "grapefruit", "honeydew", "jujube", "kiwi", "lime", "mango", "pineapple", "raspberry", "star fruit", "tomato", "watermelon"); List<String> result = fruits.stream() .filter(fruit -> fruit.length() >= 8) .limit(3) .toList();
  3. Copyright © 2025, HappyCoders.eu avocado banana cantaloupe dragon fruit fig

    grapefruit honeydew jujube kiwi lime mango pineapple raspberry star fruit tomato watermelon avocado banana cantaloupe dragon fruit fig grapefruit cantaloupe dragon fruit grapefruit ✘ ✘ ✔ ✔ ✘ ✔ cantaloupe dragon fruit grapefruit ✔ ✔ ✔ cantaloupe dragon fruit stream() toList() filter(…) limit(…) 3 grapefruit “STOP!” ✘ ✘ ✘ ✘ ✘ ✘ ✘ ✘ ✘ ✘
  4. Copyright © 2025, HappyCoders.eu Intermediäre Operationen des JDK window!!! fold!!!

    map(...) flatMap(...) filter(...) limit(...) mapMulti(...) distinct() sorted() skip(...) takeWhile(...) dropWhile(...) peek(...)
  5. Copyright © 2025, HappyCoders.eu Demo the two of and a

    be in that the be two of and a in that
  6. Copyright © 2025, HappyCoders.eu Vordefinierte Stream Gatherer windowFixed(int windowSize) windowSliding(int

    windowSize) fold(Supplier<R> initial, BiFunction<? super R, ? super T, ? extends R> folder) scan(Supplier<R> initial, BiFunction<? super R, ? super T, ? extends R> scanner) mapConcurrent(int maxConcurrency, Function<? super T, ? extends R> mapper)
  7. Copyright © 2025, HappyCoders.eu • Keine Gatherer für die primitiven

    Streams IntStream, LongStream und DoubleStream • Kein Zugriff auf die Charakteristika des Streams, keine Indikation, welche Charakteristika beibehalten werden Performance + Grenzen
  8. Copyright © 2025, HappyCoders.eu int[] array = IntStream.iterate(1, i ->

    i + 1) .filter(i -> i % 7 == 0) .limit(3) .toArray();
  9. Copyright © 2025, HappyCoders.eu List<String> words = . . .

    Schneller! long count = words.stream() .map(String::toUpperCase) .count(); long count = words.stream() .gather(mapping(String::toUpperCase)) .count(); 3,7 µs 861529,6 µs