# Java Collect(): So nutzen Sie Reduktionsoperationen

Stream Collectors sind ein leistungsstarkes Feature der **Java 8 Stream API**, mit dem Sie Daten effizient sammeln und verarbeiten können. Wir erklären Ihnen den Aufbau und die Einsatzmöglichkeiten der Java-Collect-Methode.

## Was sind die Anwendungsbereiche für Java Collect()?

Ein Stream Collector kann verwendet werden, um eine Liste, ein Set oder eine Map aus einem Stream zu erstellen. Ein Stream ist eine Sequenz von Elementen, die nacheinander verarbeitet werden. Die Collector-Schnittstelle bietet eine Reihe von **Reduktionsoperationen** für Daten in einer Stream-Pipeline. Es handelt sich hierbei um Terminaloperationen, die die Ergebnisse von Zwischenschritten sammeln und zusammenführen.

Collectors können beispielsweise genutzt werden, um Objekte aus einem Stream zu filtern oder zu sortieren. Auch **Aggregation** ist möglich, etwa das Summieren von Zahlen, Zusammenfassen von Strings oder Zählen von Elementen. Des Weiteren besitzen Collectors Funktionen, um die Inhalte eines Streams in eine bestimmte Struktur zu transformieren. So können Sie beispielsweise eine Liste in eine Map umwandeln. Gruppierungen helfen, Elemente mit bestimmten Eigenschaften oder Bedingungen zu kategorisieren. Vor allem aber haben Stream Collectors den Vorteil, dass sie **Daten mithilfe mehrerer Threads parallel verarbeiten**. Dadurch können Operationen, insbesondere bei großen Datenmengen, deutlich schneller und effizienter durchgeführt werden.

## Das ist die Syntax von Java Collect()

Die Methode akzeptiert einen Collector als Argument, der beschreibt, wie die Elemente des Streams gesammelt und aggregiert werden sollen. Ein **Collector ist ein Interface**, das verschiedene Methoden bereitstellt, um die Elemente des Streams in eine bestimmte Form zusammenzuführen – z. B. in eine Liste, ein Set oder eine Map.

Es gibt zwei Arten der Java-Collect-Methode:

1. &lt;R&gt; R collect(Supplier&lt;R&gt; supplier, BiConsumer&lt;R, ? super T&gt; accumulator,BiConsumer&lt;R, R&gt; combiner)
2. &lt;R, A&gt; R collect(Collector&lt;? super T, A, R&gt; collector)

Die erste Variante hat als Argument drei Funktionen:

- **supplier**: Erstellt einen Container, der für die Zwischenergebnisse verwendet wird.
- **accumulator**: Berechnet das Endergebnis.
- **combiner**: Kombiniert die Ergebnisse von parallelen Stream-Operationen.

Diese vordefinierten Collectors sind bereits in der Standardbibliothek enthalten und können einfach importiert und verwendet werden.

Die zweite Variante nimmt als Argument einen Collector und gibt das Ergebnis zurück.

- **R**: der Typ des Ergebnisses
- **T**: der Typ der Elemente im Stream
- **A**: der Typ des Accumulators, der den Zwischenzustand der Collector-Operation speichert
- **collector**: Führt die Reduktionsoperation aus.

Durch die Verwendung dieser Variante können Entwickler und Entwicklerinnen **maßgeschneiderte Collectors** erstellen, die speziell auf ihre Anforderungen zugeschnitten sind und eine höhere Flexibilität und Kontrolle über den Reduktionsprozess bieten.

## Praktische Beispiele für den Einsatz von Java Collect()

Im Folgenden illustrieren wir verschiedene Funktionen der `Stream.collect()`-Methode. Sie sollten bereits mit den grundlegenden [Java-Operatoren](https://www.ionos.de/digitalguide/websites/web-entwicklung/java-operator/ "Java-Operator") vertraut sein, bevor Sie in das **Collection Framework** einsteigen.

### Eine Liste von Strings verketten

Mit Java Collect() können wir eine Liste von Strings **konkatenieren**, um einen neuen String zu erhalten:

```Java
List<String> letters = List.of("a", "b", "c", "d", "e");
// without combiner function
StringBuilder result = letters.stream().collect(StringBuilder::new, (x, y) -> x.append(y),
		(a, b) -> a.append(",").append(b));
System.out.println(result.toString());
// with combiner function
StringBuilder result1 = letters.parallelStream().collect(StringBuilder::new, (x, y) -> x.append(y),
		(a, b) -> a.append(",").append(b));
System.out.println(result1.toString());
```

Wir erhalten die Ausgabe:

```Java
abcde
a, b, c, d, e
```

Bei der ersten Berechnung liegt nur eine StringBuilder-Instanz vor und es wurde keine Combiner-Funktion verwendet. Deshalb lautet das Ergebnis `abcde`.

Im zweiten Output erkennen wir, dass die Combiner-Funktion die StringBuilder-Instanzen zusammengeführt und sie mit einem Komma getrennt hat.

### Elemente mit toList() in einer Liste sammeln

Wir können mit der Funktion `filter()` bestimmte Elemente einer Liste selektieren und sie in einer neuen Liste mit `toList()` speichern.

```Java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
List<Integer> oddNumbers = numbers.stream().filter(x -> x % 2 != 0).collect(Collectors.toList());
System.out.println(oddNumbers);
```

Die neue Liste enthält nun ausschließlich ungerade Zahlen:

```Java
[1, 3, 5, 7]
```

### Elemente mit toSet() in einem Set sammeln

Analog können wir aus ausgewählten Elementen ein neues Set erstellen. Die Reihenfolge darf in einem Set **ungeordnet** sein.

```Java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
Set<Integer> evenNumbers = numbers.parallelStream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
System.out.println(evenNumbers);
```

Dies führt zur Ausgabe:

```Java
[2, 4, 6]
```

### Elemente mit toMap() in einer Map sammeln

Eine Map in Verbindung mit Java Collect() ordnet jedem Schlüssel einen Wert zu.

```Java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
Map<Integer, String> mapEvenNumbers = numbers.parallelStream().filter(x -> x % 2 == 0)
		.collect(Collectors.toMap(Function.identity(), x -> String.valueOf(x)));
System.out.println(mapEvenNumbers);
```

In der Ausgabe sehen wir, dass der Input, der aus geraden Zahlen besteht, seinen identischen Werten zugeordnet wurde:

```Java
{2=2, 4=4, 6=6}
```

### Elemente mit joining() in einer Zeichenkette kombinieren

Die `joining()`-Methode fügt jedes Element im Stream in der Reihenfolge hinzu, in der sie vorkommen und verwendet **ein Trennzeichen, um die Elemente zu trennen**. Das Trennzeichen wird als Argument an `joining()` übergeben. Wenn kein Trennzeichen angegeben wird, benutzt `joining()` den leeren String `""`.

```Java
jshell> String result1 = Stream.of("a", "b", "c").collect(Collectors.joining());
jshell> String result2 = Stream.of("a", "b", "c").collect(Collectors.joining(",", "{", "}"));
```

Die Ergebnisse lauten:

```Java
result1 ==> "abc"
result2 ==> "{a,b,c}"
```


This is a markdown version of: [https://www.ionos.de/digitalguide/websites/web-entwicklung/java-stream-collect/](https://www.ionos.de/digitalguide/websites/web-entwicklung/java-stream-collect/) for AI/LLM consumption.