Java 8 Stream skip () vs limit ()

Java 8 Stream skip () vs limit ()

1. Introdução

Neste breve artigo, vamos falar sobre os métodosskip()elimit() deJava Stream APIe destacar suas semelhanças e diferenças.

Embora essas duas operações possam parecer bastante parecidas no início, elas realmente se comportam de maneira muito diferente e não são intercambiáveis. Na verdade, eles são complementares e podem ser úteis quando usados ​​juntos. Continue lendo para saber mais sobre eles.

2. O Métodoskip()

O métodoskip(n) é umintermediate operation that discards the first n elements of a stream. O parâmetron não pode ser negativo e, se for maior do que o tamanho do fluxo,skip() retorna um fluxo vazio.

Vamos ver um exemplo:

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 + " "));

Neste fluxo, estamos pegando os números pares do fluxo, mas pulamos os dois primeiros. Portanto, nosso resultado é:

6 8 10

Quando este fluxo é executado, oforEach começa a pedir itens. Quando chega askip(), esta operação sabe que os dois primeiros itens devem ser descartados, então não os adiciona ao fluxo resultante. Depois disso, ele cria e retorna um fluxo com os itens restantes.

Para isso, a operaçãoskip() deve manter o estado dos elementos vistos a cada momento. Por esse motivo,we say that skip() is a stateful operation.

3. O Métodolimit()

O métodolimit(n) é outrointermediate operation that returns a stream not longer than the requested size. Como antes, o parâmetron não pode ser negativo.

Vamos usá-lo em um exemplo:

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 + " "));

Nesse caso, estamos pegando apenas dois números pares de nosso fluxo deint:

2 4

Como é o caso da operaçãoskip(),limit() também é uma operação com estado, pois deve manter o estado dos itens que estão sendo coletados.

Porém, ao contrário deskip(), que consome todo o fluxo, assim quelimit() atinge o número máximo de itens, ele não consome mais itens e simplesmente retorna o fluxo resultante. Portanto,we say that limit() is a short-circuiting operation.

Ao trabalhar com fluxos infinitos,limit() pode ser muito útil para truncar um fluxo em um finito:

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

Neste exemplo, estamos truncando um fluxo infinito de números em um fluxo com apenas dez números pares.

4. Combinandoskip() elimit()

Como mencionamos anteriormente, as operaçõesskipelimit são complementares e, se as combinarmos, podem ser muito úteis em alguns casos.

Vamos imaginar que queremos modificar nosso exemplo anterior para que obtenha números pares em lotes de dez. Podemos fazer isso simplesmente usandoskip() elimit() no mesmo fluxo:

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

Como podemos ver, podemos paginar facilmente através do fluxo com esse método. Mesmo sendo uma paginação muito simplista, podemos ver o quão poderoso isso pode ser ao fatiar um fluxo.

5. Conclusão

Neste breve artigo, mostramos as semelhanças e diferenças dos métodosskip()elimit() da API Java Stream. Também implementamos alguns exemplos simples para mostrar como podemos usar esses métodos.

Como sempre, o código-fonte completo dos exemplos está disponívelover on GitHub.