Streams in Java zusammenführen

1. Übersicht

In diesem kurzen Artikel erklären wir verschiedene Möglichkeiten zum Zusammenführen von Java- Streams - was keine sehr intuitive Operation ist.

2. Verwenden von Plain Java

Die JDK 8 Stream- Klasse verfügt über einige nützliche statische Dienstprogrammmethoden. Schauen wir uns die concat () -Methode genauer an .

2.1. Zwei Streams zusammenführen

Der einfachste Weg, 2 Streams zu kombinieren, ist die statische Stream.concat () -Methode:

@Test public void whenMergingStreams_thenResultStreamContainsElementsFromBoth() { Stream stream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream resultingStream = Stream.concat(stream1, stream2); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6), resultingStream.collect(Collectors.toList())); } 

2.2. Zusammenführen mehrerer Streams s

Wenn wir mehr als 2 Streams zusammenführen müssen, werden die Dinge etwas komplexer. Eine Möglichkeit besteht darin, die ersten beiden Streams zu verketten und dann das Ergebnis mit dem nächsten zu verketten und so weiter.

Das nächste Code-Snippet zeigt dies in Aktion:

@Test public void given3Streams_whenMerged_thenResultStreamContainsAllElements() { Stream stream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream stream3 = Stream.of(18, 15, 36); Stream resultingStream = Stream.concat( Stream.concat(stream1, stream2), stream3); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36), resultingStream.collect(Collectors.toList())); } 

Wie wir sehen können, wird dieser Ansatz für mehr Streams nicht mehr durchführbar. Natürlich können wir Zwischenvariablen oder Hilfsmethoden erstellen, um die Lesbarkeit zu verbessern, aber hier ist eine bessere Option:

@Test public void given4Streams_whenMerged_thenResultStreamContainsAllElements() { Stream stream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream stream3 = Stream.of(18, 15, 36); Stream stream4 = Stream.of(99); Stream resultingStream = Stream.of( stream1, stream2, stream3, stream4) .flatMap(i -> i); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36, 99), resultingStream.collect(Collectors.toList())); } 

Was hier passiert ist:

  • Wir erstellen zuerst einen neuen Stream , der die 4 Streams enthält, was zu einem Stream führt
  • Dann machen wir flatMap () dies mit der Identitätsfunktion in einen Stream

3. Verwenden von StreamEx

StreamEx ist eine Open-Source-Java-Bibliothek, die die Möglichkeiten von Java 8-Streams erweitert. Es verwendet die StreamEx- Klasse als Erweiterung der Stream- Schnittstelle des JDK .

3.1. Merging - Stream s

Mit der StreamEx-Bibliothek können wir Streams mithilfe der Instanzmethode append () zusammenführen :

@Test public void given4Streams_whenMerged_thenResultStreamContainsAllElements() { Stream stream1 = Stream.of(1, 3, 5); Stream stream2 = Stream.of(2, 4, 6); Stream stream3 = Stream.of(18, 15, 36); Stream stream4 = Stream.of(99); Stream resultingStream = StreamEx.of(stream1) .append(stream2) .append(stream3) .append(stream4); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36, 99), resultingStream.collect(Collectors.toList())); } 

Da es sich um eine Instanzmethode handelt, können wir sie einfach verketten und mehrere Streams anhängen.

Beachten Sie, dass wir mit toList () auch eine Liste aus dem Stream erstellen können, wenn wir die resultierende Variable Stream in den StreamEx- Typ eingeben .

3.2. Zusammenführen von Streams mit prepend ()

StreamEx enthält auch eine Methode namens prepend (), die voreinander Elemente hinzufügt :

@Test public void given3Streams_whenPrepended_thenResultStreamContainsAllElements() { Stream stream1 = Stream.of("foo", "bar"); Stream openingBracketStream = Stream.of("["); Stream closingBracketStream = Stream.of("]"); Stream resultingStream = StreamEx.of(stream1) .append(closingBracketStream) .prepend(openingBracketStream); assertEquals( Arrays.asList("[", "foo", "bar", "]"), resultingStream.collect(Collectors.toList())); } 

4. Verwenden von Jooλ

jOOλ ist eine JDK 8-kompatible Bibliothek, die nützliche Erweiterungen für das JDK bietet. Die wichtigste Stream-Abstraktion heißt hier Seq . Beachten Sie, dass dies ein sequentieller und geordneter Stream ist, sodass das Aufrufen von parallel () keine Auswirkung hat.

4.1. Streams zusammenführen

Genau wie die StreamEx-Bibliothek verfügt jOOλ über eine append () -Methode:

@Test public void given2Streams_whenMerged_thenResultStreamContainsAllElements() { Stream seq1 = Stream.of(1, 3, 5); Stream seq2 = Stream.of(2, 4, 6); Stream resultingSeq = Seq.ofType(seq1, Integer.class) .append(seq2); assertEquals( Arrays.asList(1, 3, 5, 2, 4, 6), resultingSeq.collect(Collectors.toList())); } 

Es gibt auch eine bequeme toList () -Methode, wenn wir die resultierende Variable See in den Typ jOOλ Seq eingeben .

4.2. Zusammenführen von Streams mit prepend ()

Da eine append () -Methode vorhanden ist, gibt es erwartungsgemäß auch eine prepend () -Methode in jOOλ:

@Test public void given3Streams_whenPrepending_thenResultStreamContainsAllElements() { Stream seq = Stream.of("foo", "bar"); Stream openingBracketSeq = Stream.of("["); Stream closingBracketSeq = Stream.of("]"); Stream resultingStream = Seq.ofType(seq, String.class) .append(closingBracketSeq) .prepend(openingBracketSeq); Assert.assertEquals( Arrays.asList("[", "foo", "bar", "]"), resultingStream.collect(Collectors.toList())); } 

5. Schlussfolgerung

Wir haben gesehen, dass das Zusammenführen von Streams mit JDK 8 relativ einfach ist. Wenn wir viel zusammenführen müssen, kann es aus Gründen der Lesbarkeit von Vorteil sein, die StreamEx- oder jOOλ-Bibliothek zu verwenden.

Sie finden den Quellcode auf GitHub.