当前位置: 首页 > 知识库问答 >
问题:

流操作应用于列表元素的顺序是什么?[重复]

苏弘盛
2023-03-14

假设我们有一个流操作的标准方法链:

Arrays.asList("a", "bc", "def").stream()
  .filter(e -> e.length() != 2)
  .map(e -> e.length())
  .forEach(e -> System.out.println(e));

JLS 中是否有任何关于将流操作应用于列表元素的顺序的保证?

例如,是否保证:

  1. 在将筛选器谓词应用于“a之前,将筛选器谓词应用于“bc”不会发生吗?
  2. 在将映射函数应用于“a”之前,将映射函数应用于“def”不会发生
  3. 1 会先打印 3

注意:我在这里特别谈论的是< code>stream(),而不是< code>parallelStream(),在后者中,映射和过滤等操作是并行完成的。

共有3个答案

邴景山
2023-03-14

不保证列表项传递给谓词lambda的顺序。流留档保证流的输出,包括遇到的顺序;它不保证实现细节,例如应用过滤器谓词的顺序。

因此,文档不会阻止筛选器读取多个元素,以相反的顺序运行对它们的谓词,然后按照它们传入的顺序将谓词传递到流输出的元素。我不知道为什么 filter() 会做这样的事情,但这样做不会破坏文档中的任何保证。

您可以从文档中推断出< code>filter()将按照集合提供元素的顺序调用元素上的谓词,因为您传递的是在list上调用< code>stream()的结果,它调用< code>Collection.stream(),并且根据Java文档,保证< code >流

返回以此集合为源的顺序< code >流。

此外,< code>filter()是无状态的:

在处理新元素时,无状态操作,如<code>filter</code>和<code>map</code>不会保留以前看到的元素的状态-每个元素都可以独立于对其他元素的操作进行处理。

因此,< code>filter很可能会按照集合提供的顺序调用元素上的谓词。

我在这里具体谈论的是< code>stream(),而不是< code>parallelStream()

请注意,Stream

南宫阳焱
2023-03-14

JLS 中是否有任何关于将流操作应用于列表元素的顺序的保证?

JLS不涵盖Streams库。您需要阅读库的Javadoc。

流还支持并行流,处理的顺序取决于实现。

在将筛选器谓词应用于“a”之前,将筛选器谓词应用于“bc”不会发生吗?

假设它会是合理的,但您不能保证它,也不应该编写需要这种保证的代码,否则您以后将无法并行化它。

在将映射函数应用于“a”之前,将映射函数应用于“def”不会发生吗?

假设这种情况确实发生是安全的,但是您不应该编写需要它的代码。

柯伟志
2023-03-14

您想知道的一切都可以在java.util.streamJavaDoc中找到。

流可能有也可能没有定义的相遇顺序。流是否具有相遇顺序取决于源和中间操作。某些流源(如列表或数组)本质上是有序的,而其他流源(例如哈希集)则不是。一些中间操作,如sorted(),可能会对其他无序流施加遭遇顺序,而其他操作可能会使有序流无序,如BaseStream.unordered()。此外,一些终端操作可能会忽略相遇顺序,例如forEach()。

如果对流进行排序,则大多数操作被限制为按其相遇顺序对元素进行操作;如果流的源是包含 [1, 2, 3] 的列表,则执行 map(x -

对于顺序流,遇到顺序的存在与否不影响性能,只影响确定性。如果流是有序的,在相同的源上重复执行相同的流管道将产生相同的结果;如果没有排序,重复执行可能会产生不同的结果。

对于并行流,放松排序约束有时可以实现更高效的执行。如果元素的排序不相关,则可以更有效地实现某些聚合操作,例如过滤重复项(distinct())或分组缩减(collector.groupingBy())。类似地,本质上与相遇顺序相关的操作,如limit(),可能需要缓冲以确保正确排序,从而破坏了并行性的好处。如果流具有相遇顺序,但用户并不特别关心该相遇顺序,则使用unordered()显式对流进行去排序可以提高某些有状态或终端操作的并行性能。然而,大多数流管道,如上面的“块权重之和”示例,即使在排序约束下,仍然可以有效地并行化。

 类似资料:
  • 问题内容: 假设我们有一个标准的流操作方法链: JLS中是否有保证将流操作应用于列表元素的顺序? 例如,是否保证: 将过滤谓词应用于不会在将过滤谓词应用于之前进行。 将映射功能应用于之前,将不会应用映射功能。 会在之前印刷吗? 注意 :我在这里专门谈论, 而不是 在预期并行执行映射和过滤之类的操作的地方。 问题答案: 您想知道的一切都可以在JavaDoc中找到。 流可能具有也可能没有定义的遇到顺序

  • 在我的Java应用程序中,我使用以下流: 列表包含9个字符串,上面的代码只对第一个执行操作,而对另一个执行操作。 如何更改代码为列表中的每个元素触发相同的操作?

  • lindex 返回名称为key的list中index位置的元素,例如: redis 127.0.0.1:6379> lindex mylist5 0

  • 问题内容: 我注意到JSON对象中元素的顺序不是原始顺序。 JSON列表的元素呢?他们的订单得到维护吗? 问题答案: 是的,JSON数组中元素的顺序得以保留。从RFC 7159开始-JavaScript对象表示法(JSON)数据交换格式 (重点是我的): 对象是零个或多个名称/值对的 无序 集合,其中名称是字符串,值是字符串,数字,布尔值,null,对象或数组。 数组是零个或多个值的 有序 序列。

  • lrem key count value 从key对应list中删除count个和value相同的元素。count为0时候删除全部,count为正,则删除匹配count个元素,如果为负数,则是从右侧扫描删除匹配count个元素。复杂度是O(N),N是List长度,因为List的值不唯一,所以要遍历全部元素,而Set只要O(log(N))。 lpop key 从list的头部删除元素,并返回删除元素

  • lpush key string 在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list类型。注意:江湖规矩一般从左端Push,右端Pop,即LPush/RPop。 lpushx 也是将一个或者多个value插入到key列表的表头,但是如果key不存在,那么就什么都不在,返回一个false【rpushx也是同样】 rpush key string 同上,在尾部添加