Come ottenere l'ultimo elemento di un flusso in Java?

1. Panoramica

L' API Java Stream era la caratteristica principale della versione Java 8. I flussi rappresentano sequenze di oggetti valutate pigramente e forniscono un'API ricca, fluente e di tipo monadico.

In questo articolo daremo una rapida occhiata ai modi per ottenere l'ultimo elemento di uno stream. Tieni presente che a causa della natura dei flussi, non è un'operazione naturale . Assicurati sempre di non lavorare con flussi infiniti .

2. Utilizzo dell'API Reduce

Reduce , in poche parole, riduce l'insieme di elementi in uno Stream a un singolo elemento.

In questo caso, ridurremo l'insieme di elementi per ottenere l'ultimo elemento nello Stream. Tieni presente che questo metodo restituirà solo risultati deterministici per Stream sequenziali .

Usiamo un elenco di stringa valori, ottenere il flusso dalla lista e poi ridurre:

List valueList = new ArrayList(); valueList.add("Joe"); valueList.add("John"); valueList.add("Sean"); Stream stream = valueList.stream(); stream.reduce((first, second) -> second) .orElse(null); 

Qui, il flusso viene ridotto a un livello in cui viene lasciato solo l'ultimo elemento. Se il flusso è vuoto, restituirà un valore nullo .

2. Utilizzo della funzione Skip

L'altro modo per ottenere l'ultimo elemento dello stream è saltare tutti gli elementi prima di esso . Ciò può essere ottenuto utilizzando la funzione Skip della classe Stream . Tieni presente che in questo caso stiamo consumando lo Stream due volte, quindi c'è un chiaro impatto sulle prestazioni .

Creiamo un elenco di valori stringa e utilizziamo la sua funzione di dimensione per determinare quanti elementi saltare per raggiungere l'ultimo elemento.

Ecco il codice di esempio che ottiene l'ultimo elemento usando skip :

List valueList = new ArrayList(); valueList.add("Joe"); valueList.add("John"); valueList.add("Sean"); long count = valueList.stream().count(); Stream stream = valueList.stream(); stream.skip(count - 1).findFirst().get(); 

"Sean" finisce per essere l'ultimo elemento.

4. Ottenere l'ultimo elemento di un flusso infinito

Cercare di ottenere l'ultimo elemento del flusso infinito porterebbe a una sequenza infinita di valutazione eseguita su elementi infiniti. Sia il salto che la riduzione non torneranno dall'esecuzione della valutazione a meno che non limitiamo il flusso infinito a un numero specifico di elementi utilizzando l' operazione limite .

Ecco il codice di esempio in cui abbiamo preso un flusso infinito e abbiamo cercato di ottenere l'ultimo elemento:

Stream stream = Stream.iterate(0, i -> i + 1); stream.reduce((first, second) -> second).orElse(null);

Di conseguenza, il flusso non tornerà dalla valutazione e finirà per interrompere l'esecuzione del programma .

5. conclusione

Abbiamo visto modi diversi per ottenere l'ultimo elemento di un flusso utilizzando sia le API reduce che quelle Skip . Abbiamo anche esaminato il motivo per cui questo non è possibile con flussi infiniti.

Abbiamo visto che ottenere l'ultimo elemento da un flusso non è facile rispetto a recuperarlo da altre strutture di dati. Ciò è dovuto alla natura pigra dei flussi che non vengono valutati a meno che non venga invocata la funzione terminale e non si sa mai se l'elemento attualmente valutato è l'ultimo.

Gli snippet di codice possono essere trovati su GitHub.