当无序时,限制和跳过操作变为无状态

时间:2016-01-29 13:21:17

标签: java java-stream stateless stateful

我的问题很简单。 java流的中间限制和跳过操作被称为有状态操作 - 我假设它们默认需要限制或跳过有序流上的前n个元素。

如果我通过调用unordered()方法或使用无序源来使输入源流无序,我们是否可以有效地说这些操作可能被认为是无状态的,或者我在这里遗漏了什么?

2 个答案:

答案 0 :(得分:3)

不,limitskip仍然是有状态操作,因为元素的处理取决于有关其他元素处理的信息(即它们是否已被处理)。

对于无序流,这些操作更容易实现,但这并不会改变它们的状态性。

你可以通过简单地问自己来说明这一点:“通过查看元素而不是其他任何内容(除了在开始整个流操作之前已知的不变信息),可以为单个元素实现此操作吗?”

答案 1 :(得分:2)

我认为您的问题与并行流有关,因为在当前的Stream API实现中,顺序流不会以任何方式使用排序。

当前并行无序skip/limit实现对每个并行任务使用大小为128的缓冲区,因此您可能会从源中读取比实际需要更多的元素。这样做是为了减少对共享原子变量的可能争用,这对于低Q任务(每个元素处理非常快的任务)可能是至关重要的。所以要回答你的问题,不,无序的skip/limit操作仍然是有状态的。

您可以使用以下程序轻松检查:

AtomicLong counter = new AtomicLong();
IntStream.range(0, 1_000_000).parallel().unordered().filter(x -> true)
        .peek(x -> counter.incrementAndGet()).limit(1000).toArray();
System.out.println(counter.get());

它打印实际从源中获取的元素数量。在我的四核系统上,此代码通常打印1280(128 * 10)或1408(128 * 11),即使请求了1000个元素。