Unione di flussi in Java

1. Panoramica

In questo rapido articolo, spieghiamo diversi modi di unire Java Streams, operazione non molto intuitiva.

2. Utilizzo di Plain Java

La classe JDK 8 Stream ha alcuni utili metodi di utilità statica. Diamo uno sguardo più da vicino al metodo concat () .

2.1. Unione di due flussi

Il modo più semplice per combinare 2 Stream è utilizzare il metodo Stream.concat () statico :

@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. Fusione di più stream s

Quando dobbiamo unire più di 2 stream, le cose diventano un po 'più complesse. Una possibilità è concatenare i primi due flussi, quindi concatenare il risultato con quello successivo e così via.

Il prossimo snippet di codice mostra questo in azione:

@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())); } 

Come possiamo vedere, questo approccio diventa irrealizzabile per più flussi. Naturalmente, possiamo creare variabili intermedie o metodi di supporto per renderlo più leggibile, ma ecco un'opzione migliore:

@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())); } 

Quello che succede qui è:

  • Per prima cosa creiamo un nuovo flusso contenente i 4 flussi, che si traduce in un flusso
  • Quindi eseguiamo flatMap () in un flusso utilizzando la funzione di identità

3. Utilizzo di StreamEx

StreamEx è una libreria Java open source che estende le possibilità di Java 8 Streams. Utilizza la classe StreamEx come miglioramento dell'interfaccia Stream di JDK .

3.1. Unione di stream s

La libreria StreamEx ci consente di unire i flussi utilizzando il metodo di istanza append () :

@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())); } 

Poiché si tratta di un metodo di istanza, possiamo facilmente concatenarlo e aggiungere più flussi.

Nota che potremmo anche creare un List fuori dallo stream usando toList () se digitiamo la variabile risultanteStream nel tipo StreamEx .

3.2. Unione di flussi utilizzando prepend ()

StreamEx contiene anche un metodo che aggiunge elementi uno prima dell'altro chiamato prepend () :

@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. Utilizzo di Jooλ

jOOλ è una libreria compatibile con JDK 8 che fornisce utili estensioni a JDK. L'astrazione di flusso più importante qui si chiama Seq . Nota che questo è un flusso sequenziale e ordinato, quindi la chiamata a parallel () non avrà alcun effetto.

4.1. Unione di flussi

Proprio come la libreria StreamEx, jOOλ ha un metodo append () :

@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())); } 

Inoltre, c'è un comodo metodo toList () se digitiamo la variabile risultanteSeq nel tipo jOOλ Seq .

4.2. Unione di stream con prepend ()

Come previsto, poiché esiste un metodo append () , c'è anche un metodo prepend () 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. conclusione

Abbiamo visto che l'unione di flussi è relativamente semplice usando JDK 8. Quando abbiamo bisogno di fare molte fusioni, potrebbe essere utile usare la libreria StreamEx o jOOλ per motivi di leggibilità.

Puoi trovare il codice sorgente su GitHub.