Java 8 Stream skip() vs limit() – Java 8 Stream skip() vs limit()

最后修改: 2019年 6月 27日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this short article, we’ll talk about the skip() and limit() methods of the Java Stream API and highlight their similarities and differences.

在这篇短文中,我们将讨论Java Stream APIskip()limit()方法,并强调它们的相似性和差异。

Even though these two operations may look quite similar at first, they actually behave very differently and are not interchangeable. Actually, they’re complementary and can be handy when used together. Keep reading to learn more about them.

尽管这两种操作一开始看起来很相似,但实际上它们的行为非常不同,不能互换。事实上,它们是互补的,一起使用时可以很方便。继续阅读以了解更多关于它们的信息。

2. The skip() Method

2、skip()方法

The skip(n) method is an intermediate operation that discards the first n elements of a stream. The n parameter can’t be negative, and if it’s higher than the size of the stream, skip() returns an empty stream.

skip(n)方法是一个中间操作,它抛弃了一个流中的前n个元素n参数不能是负数,如果它高于流的大小,skip()将返回一个空流。

Let’s see an example:

让我们看一个例子。

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 this stream, we’re picking up the even numbers of the stream but we skip the first two. Therefore, our result is:

在这个流中,我们要捡起流中的偶数,但我们跳过前两个。因此,我们的结果是。

6 8 10

When this stream is executed, the forEach starts asking for items. When it gets to skip(), this operation knows that the first two items have to be discarded, so it doesn’t add them to the resulting stream. After that, it creates and returns a stream with the remaining items.

当这个流被执行时,forEach开始询问项目。当它到达skip()时,这个操作知道前两个项目必须被丢弃,所以它不会将它们添加到结果流中。之后,它创建并返回一个带有剩余项的流。

In order to do this, the skip() operation has to keep the state of the elements seen at each moment. For this reason, we say that skip() is a stateful operation.

为了做到这一点,skip()操作必须保持每个时刻看到的元素的状态。由于这个原因,我们说skip()是一个有状态的操作

3. The limit() Method

3、limit()方法

The limit(n) method is another intermediate operation that returns a stream not longer than the requested size. As before, the n parameter can’t be negative.

limit(n)方法是另一个中间操作,它返回一个不长于请求大小的流。和以前一样,n参数不能是负数。

Let’s use it in an example:

让我们在一个例子中使用它。

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 this case, we’re picking up just two even numbers from our stream of int:

在这种情况下,我们从我们的int流中只挑出两个偶数。

2 4

As is the case with the skip() operation, limit() is also a stateful operation since it has to keep the state of the items that are being picked up.

skip()操作的情况一样,limit()也是一个有状态的操作,因为它必须保持被拾取的项目的状态。

But unlike skip(), which consumes the entire stream, as soon as limit() reaches the maximum number of items, it doesn’t consume any more items and simply returns the resulting stream. Hence, we say that limit() is a short-circuiting operation.

但是与 skip()不同的是,limit()会消耗整个流,一旦limit()达到了项目的最大数量,它就不会再消耗任何项目,而只是返回所得到的流。因此,我们说,limit()是一个短路操作

When working with infinite streams, limit() can be very useful for truncating a stream into a finite one:

当处理无限的流时,limit()可以非常有用地将一个流截断成一个有限的流。

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

In this example, we’re truncating an infinite stream of numbers into a stream with only ten even numbers.

在这个例子中,我们要把一个无限的数字流截断成一个只有10个偶数的数字流。

4. Combining skip() and limit()

4.结合skip()limit()

As we mentioned earlier, the skip and limit operations are complementary, and if we combine them, they can be very helpful in some cases.

正如我们前面提到的,skiplimit操作是互补的,如果我们把它们结合起来,在某些情况下会有很大帮助。

Let’s imagine that we want to modify our previous example so that it gets even numbers in batches of ten. We can do that simply by using both skip() and limit() on the same stream:

让我们想象一下,我们想修改我们之前的例子,使其以10个为一个批次获得偶数。我们可以通过在同一个流上同时使用skip()limit()来实现。

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

As we can see, we can paginate through the stream quite easily with this method. Even though this is a very simplistic pagination, we can see how powerful this can be when slicing a stream.

正如我们所看到的,我们可以用这个方法很容易地对流进行分页。尽管这是一个非常简单的分页,但我们可以看到,在对流进行分片时,这可以是多么强大。

5. Conclusion

5.结论

In this brief article, we’ve shown the similarities and differences of the skip() and limit() methods of the Java Stream API. We’ve also implemented some simple examples to show how we can use these methods.

在这篇简短的文章中,我们展示了Java Stream API的skip()limit()方法的相似性和区别。我们还实现了一些简单的例子来展示我们如何使用这些方法。

As always, the full source code for the examples is available over on GitHub.

一如既往,这些示例的完整源代码可在GitHub上获取