Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> Java

Java 8 Streams: Deklarative Datenverarbeitung – filter, map, reduce, collect & parallel

Was ist ein Stream?

Ein Stream ist eine Sequenz von Elementen, die aggregate Operationen (filter, map, reduce, …) unterstützt. Anders als Collections:

Stream erzeugen

// Aus Collection
list.stream()           // sequential
list.parallelStream()   // parallel

// Aus Array
Arrays.stream(array)
Stream.of("a", "b", "c")

// Unendlich
Stream.iterate(0, n -> n + 2) // 0,2,4,6...
Stream.generate(() -> Math.random())

Wichtige Intermediate Operations

Operation Beschreibung Beispiel
filter(Predicate) Behält Elemente, die Prädikat erfüllen .filter(s -> !s.isEmpty())
map(Function) Transformiert jedes Element .map(String::toUpperCase)
flatMap(Function) Transformiert zu Stream & flacht auf .flatMap(s -> Stream.of(s.split(" ")))
distinct() Entfernt Duplikate (equals)
sorted() / sorted(Comparator) Sortiert Stream .sorted(Comparator.comparing(String::length))
limit(n) Begrenzt auf erste n Elemente .limit(10)
skip(n) Überspringt erste n Elemente .skip(5)
peek(Consumer) Side-Effect pro Element (Debugging) .peek(System.out::println)

Terminal Operations

Operation Rückgabe Beschreibung
forEach(Consumer) void Führt Aktion für jedes Element aus.
collect(Collector) R Sammelt in Collection, String, Map, …
reduce(BinaryOperator) Optional<T> Reduziert auf einzelnen Wert.
reduce(identity, BinaryOperator) T Reduziert mit Startwert.
count() long Anzahl Elemente.
anyMatch/allMatch/noneMatch(Predicate) boolean Kurzschluss-Prüfung.
findFirst/findAny() Optional<T> Findet Element.
min/max(Comparator) Optional<T> Minimum/Maximum.

Collectors – Ergebnisse sammeln

// To List/Set
list.stream().collect(Collectors.toList());
list.stream().collect(Collectors.toSet());

// To Map
stream.collect(Collectors.toMap(
    User::getId, User::getName, (u1,u2)->u1, LinkedHashMap::new));

// Joining Strings
stream.map(Object::toString).collect(Collectors.joining(", "));

// Grouping / Partitioning
stream.collect(Collectors.groupingBy(User::getDepartment));
stream.collect(Collectors.partitioningBy(u -> u.isActive()));

// Statistics
IntSummaryStatistics stats = intStream.summaryStatistics();
// stats.getMax(), getMin(), getSum(), getAverage(), getCount()

Parallel Processing

// Einfach umschalten
long count = list.parallelStream()
    .filter(s -> s.length() > 3)
    .count();

// Oder: sequential() / parallel() in Pipeline
list.stream().parallel().filter(...).sequential().map(...).collect(...)

Vorsicht: Parallel nur bei CPU-intensiven, nebenwirkungsfreien Operationen & großer Datenmenge. Overhead bei kleinen Streams!

Vollständiges Beispiel: Java 7 vs. Java 8

import java.util.*;
import java.util.stream.*;
import java.util.IntSummaryStatistics;

public class StreamDemo {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        List<Integer> integers = Arrays.asList(1, 2, 13, 4, 15, 6, 17, 8, 19);

        // --- Java 7 Style (Imperativ) ---
        long emptyCount = 0;
        for (String s : strings) if (s.isEmpty()) emptyCount++;
        System.out.println("Leer (Java 7): " + emptyCount);

        List<String> filtered = new ArrayList<>();
        for (String s : strings) if (!s.isEmpty()) filtered.add(s);
        System.out.println("Gefiltert (Java 7): " + filtered);

        // --- Java 8 Style (Deklarativ) ---
        emptyCount = strings.stream().filter(String::isEmpty).count();
        System.out.println("Leer (Java 8): " + emptyCount);

        filtered = strings.stream()
            .filter(s -> !s.isEmpty())
            .collect(Collectors.toList());
        System.out.println("Gefiltert (Java 8): " + filtered);

        // Quadrate einzig
        List<Integer> squares = numbers.stream()
            .map(n -> n * n)
            .distinct()
            .collect(Collectors.toList());
        System.out.println("Quadrate: " + squares); // [9, 4, 49, 25]

        // Statistiken
        IntSummaryStatistics stats = integers.stream()
            .mapToInt(Integer::intValue)
            .summaryStatistics();
        System.out.printf("Max: %d, Min: %d, Sum: %d, Avg: %.2f%n",
            stats.getMax(), stats.getMin(), stats.getSum(), stats.getAverage());

        // Zufallszahlen sortiert
        new Random().ints().limit(10).sorted().forEach(System.out::println);
    }
}

Fazit

Streams verschieben den Fokus von „wie“ (Schleifen, Indizes, temporäre Variablen) zu „was“ (Transformationen, Filter, Aggregationen). Das Ergebnis: kürzerer, lesbarer, wartbarer und leichter parallelisierbarer Code. Meistern Sie die Core-Operations (filter, map, flatMap, collect, reduce) – sie decken 90 % aller Use Cases ab.

Java

  1. Java Operatoren meistern: Typen, Syntax und praktische Beispiele
  2. Java Kommentare: Typen, Verwendung und Best Practices
  3. Java Enhanced For-Schleife meistern: Syntax, Beispiele und Best Practices
  4. Java Strings meistern: Erstellung, Methoden und Best Practices
  5. Java-Schnittstellen meistern: Konzepte, Implementierung und Best Practices
  6. Java anonyme innere Klassen meistern: Definition, Syntax und praktische Beispiele
  7. Java Try-With-Resources meistern: Automatisches Ressourcenmanagement erklärt
  8. Java Annotations erklärt: Typen, Platzierung und praktische Beispiele
  9. Java Assertions: Praktischer Leitfaden zur Fehlererkennung und Code-Reliabilität
  10. Zufallszahlen in Java generieren: Praktischer Leitfaden mit Random und Math.random