Java 8 Stream:limit()和skip()之间的区别 [英] Java 8 Stream: difference between limit() and skip()

查看:372
本文介绍了Java 8 Stream:limit()和skip()之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谈论 Stream s,当我执行这段代码时

Talking about Streams, when I execute this piece of code

public class Main {
    public static void main(String[] args) {
        Stream.of(1,2,3,4,5,6,7,8,9)
        .peek(x->System.out.print("\nA"+x))
        .limit(3)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));
    }
}

我得到这个输出

A1B1C1
A2B2C2
A3B3C3

因为将我的流限制为前三个组件会强制执行操作 A B C 仅执行三次。

because limiting my stream to the first three components forces actions A, B and C to be executed only three times.

尝试使用 skip()方法对最后三个元素执行类似计算,显示不同的行为:此

Trying to perform an analogous computation on the last three elements by using skip() method, shows a different behaviour: this

public class Main {
    public static void main(String[] args) {
        Stream.of(1,2,3,4,5,6,7,8,9)
        .peek(x->System.out.print("\nA"+x))
        .skip(6)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));
    }
}

输出此

A1
A2
A3
A4
A5
A6
A7B7C7
A8B8C8
A9B9C9

为什么,在这种情况下,行动 A1 A6 正在执行?它必须与 limit 短路状态中间操作,而跳过不是,但我不明白这个属性的实际含义。是否只是跳过之前的所有操作都被执行而不是每个人都在限制之前?

Why, in this case, actions A1 to A6 are being executed? It must have something to do with the fact that limit is a short-circuiting stateful intermediate operation, while skip is not, but I don't understand practical implications of this property. Is it just that "every action before skip is executed while not everyone before limit is"?

推荐答案

这里有两个流管道。

这些流管道每个都由一个源,几个中间操作和一个终端操作组成。

These stream pipelines each consist of a source, several intermediate operations, and a terminal operation.

但中间操作是懒惰的。这意味着除非下游操作需要项目,否则不会发生任何事情。如果是,那么中间操作会完成生成所需项目所需的全部操作,然后再次等待直到请求另一项,依此类推。

But the intermediate operations are lazy. This means that nothing happens unless a downstream operation requires an item. When it does, then the intermediate operation does all it needs to produce the required item, and then again waits until another item is requested, and so on.

终端操作通常都是渴望。也就是说,他们要求流中的所有项目都是他们完成所需的。

The terminal operations are usually "eager". That is, they ask for all the items in the stream that are needed for them to complete.

所以你应该把管道视为 forEach 向它后面的流询问下一个项目,然后该流询问它后面的流,依此类推,一直到源。

So you should really think of the pipeline as the forEach asking the stream behind it for the next item, and that stream asks the stream behind it, and so on, all the way to the source.

考虑到这一点,让我们看看我们对你的第一个管道有什么:

With that in mind, let's see what we have with your first pipeline:

Stream.of(1,2,3,4,5,6,7,8,9)
        .peek(x->System.out.print("\nA"+x))
        .limit(3)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));

因此, forEach 正在要求第一项。这意味着B peek 需要一个项目,并询问 limit 输出流,这意味着 limit 将需要询问A peek ,这将转到源代码。给出了一个项目,并一直到 forEach ,然后你得到你的第一行:

So, the forEach is asking for the first item. That means the "B" peek needs an item, and asks the limit output stream for it, which means limit will need to ask the "A" peek, which goes to the source. An item is given, and goes all the way up to the forEach, and you get your first line:

A1B1C1

forEach 要求另一个项目,然后另一个项目。每次,请求都在流上传播并执行。但是当 forEach 询问第四项时,当请求到达 limit 时,它知道它已经给出了它允许给予的所有物品。

The forEach asks for another item, then another. And each time, the request is propagated up the stream, and performed. But when forEach asks for the fourth item, when the request gets to the limit, it knows that it has already given all the items it is allowed to give.

因此,它不是要求A偷看另一个物品。它立即指示其项目已耗尽,因此不再执行任何操作, forEach 终止。

Thus, it is not asking the "A" peek for another item. It immediately indicates that its items are exhausted, and thus, no more actions are performed and forEach terminates.

什么发生在第二个管道?

What happens in the second pipeline?

    Stream.of(1,2,3,4,5,6,7,8,9)
    .peek(x->System.out.print("\nA"+x))
    .skip(6)
    .peek(x->System.out.print("B"+x))
    .forEach(x->System.out.print("C"+x));

再次, forEach 要求第一个项目。这是传播回来的。但是当它到达跳过时,它知道它必须从其上游请求6个项目才能通过下游。因此它在A peek 的上游发出请求,使用它而不将其传递到下游,发出另一个请求,依此类推。所以A偷看得到6个项目请求并产生6个打印,但这些项目不会传递下来。

Again, forEach is asking for the first item. This is propagated back. But when it gets to the skip, it knows it has to ask for 6 items from its upstream before it can pass one downstream. So it makes a request upstream from the "A" peek, consumes it without passing it downstream, makes another request, and so on. So the "A" peek gets 6 requests for an item and produces 6 prints, but these items are not passed down.

A1
A2
A3
A4
A5
A6

跳过的第7个请求中,该项目向下传递到B,并从它传递到 forEach ,所以完整打印完成:

On the 7th request made by skip, the item is passed down to the "B" peek and from it to the forEach, so the full print is done:

A7B7C7

那就像以前一样。 skip 现在,无论何时收到请求,都要求上游项目并将其传递到下游,因为它知道它已经完成了跳过工作。所以其余的印刷品都会通过整个管道,直到源耗尽。

Then it's just like before. The skip will now, whenever it gets a request, ask for an item upstream and pass it downstream, as it "knows" it has already done its skipping job. So the rest of the prints are going through the entire pipe, until the source is exhausted.

这篇关于Java 8 Stream:limit()和skip()之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆