Java 8 Stream skip () vs limit ()

1. Introduzione

In questo breve articolo parleremo dei metodi skip () e limit () dell'API Java Stream ed evidenzieremo le loro somiglianze e differenze.

Anche se queste due operazioni possono sembrare abbastanza simili all'inizio, in realtà si comportano in modo molto diverso e non sono intercambiabili. In realtà, sono complementari e possono essere utili se usati insieme. Continua a leggere per saperne di più su di loro.

2. Il metodo skip ()

Il metodo skip (n) è un'operazione intermedia che elimina i primi n elementi di un flusso . Il parametro n non può essere negativo e, se è maggiore della dimensione del flusso, skip () restituisce un flusso vuoto.

Vediamo un esempio:

Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .filter(i -> i % 2 == 0) .skip(2) .forEach(i -> System.out.print(i + " "));

In questo flusso, stiamo rilevando i numeri pari dello streaming ma saltiamo i primi due. Pertanto, il nostro risultato è:

6 8 10

Quando questo flusso viene eseguito, forEach inizia a chiedere elementi. Quando arriva a skip () , questa operazione sa che i primi due elementi devono essere scartati, quindi non li aggiunge al flusso risultante. Successivamente, crea e restituisce un flusso con gli elementi rimanenti.

Per fare ciò, l' operazione skip () deve mantenere lo stato degli elementi visti in ogni momento. Per questo motivo, diciamo che skip () è un'operazione con stato .

3. Il metodo limit ()

Il metodo limit (n) è un'altra operazione intermedia che restituisce un flusso non più lungo della dimensione richiesta . Come prima, il parametro n non può essere negativo.

Usiamolo in un esempio:

Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .filter(i -> i % 2 == 0) .limit(2) .forEach(i -> System.out.print(i + " "));

In questo caso, stiamo prendendo solo due numeri pari dal nostro flusso di int :

2 4

Come nel caso dell'operazione skip () , anche limit () è un'operazione con stato poiché deve mantenere lo stato degli elementi che vengono raccolti.

Ma a differenza di skip () , che consuma l'intero flusso, non appena limit () raggiunge il numero massimo di elementi, non consuma più elementi e restituisce semplicemente il flusso risultante. Quindi, diciamo che limit () è un'operazione di cortocircuito .

Quando si lavora con flussi infiniti, limit () può essere molto utile per troncare un flusso in uno finito:

Stream.iterate(0, i -> i + 1) .filter(i -> i % 2 == 0) .limit(10) .forEach(System.out::println);

In questo esempio, stiamo troncando un flusso infinito di numeri in un flusso con solo dieci numeri pari.

4. Combinazione di skip () e limit ()

Come accennato in precedenza, le operazioni di salto e limite sono complementari e, se le combiniamo, in alcuni casi possono essere molto utili.

Immaginiamo di voler modificare il nostro esempio precedente in modo che ottenga numeri pari in gruppi di dieci. Possiamo farlo semplicemente usando sia skip () che limit () sullo stesso flusso:

private static List getEvenNumbers(int offset, int limit) { return Stream.iterate(0, i -> i + 1) .filter(i -> i % 2 == 0) .skip(offset) .limit(limit) .collect(Collectors.toList()); }

Come possiamo vedere, possiamo impaginare lo stream abbastanza facilmente con questo metodo. Anche se questa è un'impaginazione molto semplicistica, possiamo vedere quanto potente possa essere quando si affetta un flusso.

5. conclusione

In questo breve articolo, abbiamo mostrato le somiglianze e le differenze dei metodi skip () e limit () dell'API Java Stream. Abbiamo anche implementato alcuni semplici esempi per mostrare come possiamo usare questi metodi.

Come sempre, il codice sorgente completo per gli esempi è disponibile su GitHub.