4

订购

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

  1. 是否有任何其他类型不具有遇到顺序属性但是HashSet
  2. 如果我对保持现有顺序或任何排序不感兴趣,通过显式调用unordered将并行计算的每个流上的中间操作是否被认为是最佳实践?
4

3 回答 3

5

除了HashSetandHashMap的集合视图,Stream.generate()还会生成一个无序的流。

不用说,由 a 生成的流Random也是无序的。另外,Stream.empty()没有报告有遭遇命令,但这并没有太大的后果……</p>

如果您知道不需要 Stream 来维护遭遇顺序,那么使用它是一个很好的做法unordered()——即使它不会提高性能,就像当前实现中的大多数操作一样,它不会造成伤害并且会证明您不关心订单的文件。这不仅适用于并行流,distinct()即使在顺序情况下,某些操作(例如 )也可能受益于无序性。

在某些情况下,考虑到当前的实现,选择正确的终端操作,findAny()而不是findFirst()意图更简洁的文档,并且也会对性能产生更大的影响。

于 2017-06-02T16:58:52.097 回答
5

相遇的顺序不过是源头的顺序。例如 In ArrayList,元素按插入顺序排序,因此流过它只会按该顺序为您提供元素。

  1. 除了HashSet,HashMap也是无序的。
  2. 如果您只对collect操作感兴趣,而不关心订购,那么您无需担心。会stream()好的。例如,如果你想说计算总和,那么你会做这样的事情:

    List<Integer> list = Arrays.asList(1,2,3);
    int sum = list.stream().collect(Collectors.summingInt(e -> e));
    

    在这种情况下,元素流入流的顺序无关紧要。

于 2017-06-02T16:34:18.603 回答
2

对于你的第二个问题,的。如果你不在乎这些,unordered 有所帮助。前段时间我有同样的问题,在这里

现在想想无序。当你有一个 List 并将每个元素乘以 2 并将其收集回一个 List 时,你会并行执行此操作。中间列表的每次合并都必须以这样一种方式发生,即顺序保留在结果列表中。您可能已经计算了第 4 个和第一个中间结果,现在需要合并它们。如果你关心顺序,你不能直接合并它们,因为这显然会破坏顺序;所以你需要计算其他中间结果并以相同的顺序合并它们

你可以想象这就像List从左到右遍历一个;从索引零到最后一个。

另一方面,如果您不关心顺序,则只要准备好,此合并就可以按任何顺序进行。您甚至可以按任何顺序读取任何元素,因为这无关紧要。

findFirstfindAny在后台使用相同的想法。假设您有一个包含 8 个元素的 List,并行处理它并且只需要返回第一个元素。您可能已经处理了最后 7 个元素但是因为您需要第一个,所以没关系 - 您仍然需要等待第一个处理。很明显为什么findAny更好......

于 2017-06-02T22:29:00.513 回答