在 Java 8 中迭代流的最快方法是什么?

What is the fastest way to iterate on a stream in Java 8?

如果我有一个集合并且我想遍历过滤后的流,那么我可以执行以下任一操作(以及更多钝选项):

for(item in collection.stream().filter(...).collect(Collectors.toList()))
for(item in collection.stream().filter(...).collect(Collectors.toSet()))

哪个更快?列表还是集合?有什么方法可以收集到简单的 Iterable 或我可以迭代的其他类型吗?

如果你只想遍历Stream的元素,没有必要将它收集到Collection,只需使用forEach :

collection.stream()
          .filter(...)
          .forEach (item -> {
                            // do something with item
                            }
                   );

Is there some way to collect to simply an Iterable or some other type I can iterate on?

如果出于某种原因您确实想使用 Stream 作为 for-each 循环的目标,则不必收集它:

for (Item item : (Iterable<Item>)
        coll.stream().filter(...)::iterator) {
}

或:

Iterable<Item> iter = coll.stream().filter(...)::iterator;
for (Item item : iter) {
}

这是有效的,因为 Iterable 是一个功能接口,即使它没有这样注释。

不过,这只是一件有趣的事情。正如 Eran 所建议的,forEach 可能是处理一般事情的 'right' 方法。 java.util.stream package descriptioniterator 描述为 "escape hatch"。

如果您不关心元素顺序,请使用 parallelStream:

collection.parallelStream().filter(...).forEach(...)

这样您就可以使用更多线程遍历集合。

要确定对于特定案例审查哪个流或并行流处理更快 @Brian Goetz 对相关 problem

的回答

如果性能是您的目标,那么根本不要使用流。流很好,但它们几乎总是比普通的旧 java 迭代慢。

什么是最快的取决于具体情况。如果纯粹为了迭代,那么ArrayList优于HashSet。迭代 ArrayList 的最快方法是 而不是 for-each 循环,而是普通的旧 i-iteration:

int size = list.size();
for (int i = 0; i < size; i++) {
    ...list.get(i)...
}

确保将循环外的大小读取到局部变量,否则会收到许多不必要的 list.size() 调用。

如果您需要过滤原始列表,只需在此循环中添加一些 if 几乎总是比使用带过滤器的流更快。