遇到订单收集 - 最佳实践&例如

时间:2017-06-02 16:31:06

标签: java java-8 java-stream spliterator

  

排序

     

Streams可能有也可能没有已定义的遭遇顺序。是否   一个流有一个遭遇顺序取决于源和   中间操作。某些流源(例如List或   数组)本质上是有序的,而其他的(如HashSet)   不是。某些中间操作(例如sorted())可能会强制执行   在其他无序流上遇到订单,其他人可能会   渲染无序的有序流,例如BaseStream.unordered()。   此外,一些终端操作可以忽略遭遇顺序,例如   的forEach()。

  1. 是否还有其他类型没有遇到订单属性但HashSet
  2. 如果我没有保留现有订单或任何类型的排序,那么通过显式调用每个流上的unordered中间操作,它被认为是最佳做法将并行计算?

3 个答案:

答案 0 :(得分:5)

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

毋庸置疑,Random生成的流也是无序的。此外,Stream.empty()没有报告有遭遇订单,但这没有太多后果......

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

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

答案 1 :(得分:4)

遭遇秩序只不过是来源的顺序。例如。在ArrayList中,元素按插入顺序排序,因此通过它进行流式处理将只按顺序为您提供元素。

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

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

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

答案 2 :(得分:2)

第二个问题。如果您不关心这些,unordered 提供帮助。我刚才有同样的问题,here

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

您可能会想到这就像从左到右穿越List;从索引零到最后一个。

另一方面,如果你不关心订单,那么只要它准备好就可以在任何订单中进行合并。你甚至可以按任何顺序读取任何元素,因为这是无关紧要的。

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