API Java 8 Streams peek ()

1. Introduzione

L'API Java Stream ci presenta una potente alternativa per l'elaborazione dei dati.

In questo breve tutorial, ci concentreremo su peek () , un metodo spesso frainteso.

2. Esempio rapido

Sporciamoci le mani e proviamo a usare peek () . Abbiamo un flusso di nomi e vogliamo stamparli sulla console.

Poiché peek () si aspetta un consumatore come unico argomento, sembra una buona soluzione, quindi proviamolo:

Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); nameStream.peek(System.out::println);

Tuttavia, lo snippet sopra non produce alcun output. Per capire perché, facciamo un rapido aggiornamento sugli aspetti del ciclo di vita dello stream.

3. Operazioni intermedie e terminali

Ricorda che i flussi hanno tre parti: un'origine dati, zero o più operazioni intermedie e zero o un'operazione terminale.

La sorgente fornisce gli elementi alla pipeline.

Le operazioni intermedie ottengono gli elementi uno per uno e li elaborano. Tutte le operazioni intermedie sono pigre e, di conseguenza, nessuna operazione avrà alcun effetto finché la pipeline non inizierà a funzionare.

Le operazioni dei terminali significano la fine del ciclo di vita del flusso. Soprattutto per il nostro scenario, avviano il lavoro in cantiere .

4. peek () Utilizzo

La ragione peek () non ha funzionato nel nostro primo esempio è che si tratta di un intermedio operazione e non abbiamo applicare un terminale operazione al gasdotto. In alternativa, avremmo potuto usare forEach () con lo stesso argomento per ottenere il comportamento desiderato:

Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); nameStream.forEach(System.out::println);

La pagina Javadoc di peek () dice: " Questo metodo esiste principalmente per supportare il debugging, dove si desidera vedere gli elementi mentre scorrono oltre un certo punto in una pipeline ".

Consideriamo questo snippet dalla stessa pagina Javadoc:

Stream.of("one", "two", "three", "four") .filter(e -> e.length() > 3) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList());

Dimostra come osserviamo gli elementi che hanno superato ogni operazione.

Inoltre, peek () può essere utile in un altro scenario: quando vogliamo alterare lo stato interno di un elemento . Ad esempio, supponiamo di voler convertire tutti i nomi degli utenti in minuscolo prima di stamparli:

Stream userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck")); userStream.peek(u -> u.setName(u.getName().toLowerCase())) .forEach(System.out::println);

In alternativa, avremmo potuto usare map () , ma peek () è più conveniente poiché non vogliamo sostituire l'elemento.

5. conclusione

In questo breve tutorial, abbiamo visto un riepilogo del ciclo di vita dello stream per capire come funziona peek () . Abbiamo anche visto due casi d'uso quotidiani quando l'uso di peek () è l'opzione più semplice.

E come al solito, gli esempi sono disponibili su GitHub.