哪些操作保持有序背景额外积分

2022-09-02 21:38:22

TL;DR;我正在寻找一个可以查找某个中间或终端操作的地方。在哪里可以找到此类文档?

编辑这不是如何确保java8流中的处理顺序?的副本,因为该问题没有提供全面的操作列表。

背景

软件包文档说:

流是否具有遭遇顺序取决于源和中间操作

在这个优秀的堆栈溢出答案中重复了这一点

为了确保在整个流操作中维护排序,您必须研究流源的文档,所有中间操作和终端操作,以确定它们是否保持顺序(或者源是否首先具有排序)。

这一切都很好,但是我应该查看哪些文档?包文档在保证排序的示例中提到,但它没有详尽的列表。Stream 类的 javadoc 记录了一些中间操作,但不是全部。以地图为例:map

返回一个流,该流由将给定函数应用于此流的元素的结果组成。

这是一个中间操作。

过滤器

返回一个流,该流由此流中与给定谓词匹配的元素组成。

这是一个中间操作。

这些都不能描述它们是否保持顺序。

这个堆栈溢出答案声称:

实际上,默认情况下,每个中间操作都保留一个顺序。唯一的例外是:

  • unordered() 它删除了排序约束。
  • sorted() 它改变了顺序。

如果未显式指定,则可以假定该操作保持顺序。即使 distinct() 也保持了顺序,尽管它增加了并行流的复杂性。

但是是否有任何官方文件来支持这一点?

额外积分


答案 1

在对源代码进行了一些研究之后,我总结了下表:

摘自:Java 流 - 第 6 部分 - 拆分器

下表显示了允许哪些操作类型修改字符:

|                        | DISTICTS | SORTED | ORDERED | SIZED | SHORT_CIRCUIT |
| ---------------------- | -------- | ------ | ------- | ----- | --------------|
| source stream          | Y        | Y      | Y       | Y     | N             |
| intermediate operation | PCI      | PCI    | PCI     | PC    | PI            |
| terminal operation     | N        | N      | PC      | N     | PI            |
  • Y - 允许有
  • P - 五月蜜饯
  • C - 五月清除。
  • I - 可能注射。
  • N - 无效;手术无关紧要。

取自 Java 流 - 流方法特征表

下表显示了每个中间操作/终端操作可以打开和关闭的特征和标志:(仅在标志上下文中相关)SHORT_CIRCUITStreamOpFlag

注意:P(保留)标志被添加到每个单元格中,除了带有CI(清除和注入)标志的单元格。

|                  |  DISTINCT |  SORTED |  ORDERED |  SIZED |  SHORT_CIRCUIT |
| ---------------- | ----------| --------| ---------| -------| ---------------|
|  filter          |           |         |          |  C     |                |
|  forEach         |           |         |  C       |        |                |
|  forEachOrdered  |           |         |          |        |                |
|  allMatch        |           |         |  C       |        |  I             |
|  distinct        |  I        |         |          |  C     |                |
|  flatMap         |  C        |  C      |          |  C     |                |
|  anyMatch        |           |         |  C       |        |  I             |
|  collect         |           |         |          |        |                |
|  unOrdered       |           |         |  C       |        |                |
|  count           |  C        |  C      |  C       |  C     |                |
|  findAny         |           |         |  C       |        |  I             |
|  findFirst       |           |         |          |        |  I             |
|  flatMapToXXX    |  C        |  C      |          |  C     |                |
|  limit           |           |         |          |  C     |  I             |
|  map             |  C        |  C      |          |        |                |
|  mapToXXX        |  C        |  C      |          |        |                |
|  max             |           |         |          |        |                |
|  min             |           |         |          |        |                |
|  noneMatch       |           |         |  C       |        |  I             |
|  peek            |           |         |          |        |                |
|  reduce          |           |         |          |        |                |
|  skip            |           |         |  C       |  I     |                |
|  sorted          |           |  I      |  I       |        |                |
|  toArray         |           |         |          |        |                |
  • C- 清除。
  • I- 注射。

答案 2

这听起来像是两个重复 - 因为你链接的两个答案实际上都解释了事情。我不知道他们是否或应该具体说他们维护秩序;它们不依赖于任何先前的状态或任何其他状态(这些是无状态操作),因此据我所知,这意味着它们保持了秩序。我从另一个角度来看,如果他们不保留顺序 - 这应该在文档中明确提及;如果从操作名称中看不明显。例如,如果它生成了一个有序的流,对我来说并不明显;因此,在它的文档中是这样说的:mapfilterStream.generate

返回无限顺序无序流,其中每个元素都由提供的供应商生成。

sorted另一方面,改变顺序是非常明显的(IMO),至少当你把这些放进去的时候 - 你明确表示你不关心顺序。 顺便说一句,不会故意做任何随机化来满足这一点,你可以在这里阅读更多。unorderedunordered

一般有两种订单:加工订单遭遇订单

您可以将邂逅订单视为从左到右的处理(假设您有一个或一个)。因此,如果您有一个不改变顺序的管道 - 元素将被馈送到(或任何其他终端操作),如从左到右所示。好吧,并非所有终端操作都是这样的。一个明显的区别是 和 ;或 a - 根本不需要保留初始顺序。或者让我们以终端操作为例 - 显然您不关心您想要哪个元素,那么为什么要首先以确切的顺序喂养呢?ListarrayCollectorforEachforEachOrderedCollectors.toSetfindAnyfindAny

另一方面,处理订单没有定义的顺序 - 对于并行处理尤其明显。因此,即使您的管道是并行的(并且元素的处理绝对不保证任何顺序),它们仍将按顺序馈送到终端操作 - 如果该终端操作需要这样的顺序。


推荐