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

5

如果我有一个集合,并且想要遍历过滤后的流,那么我可以选择以下任意一种方法(还有许多更加晦涩的选项):

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

哪个更快?列表还是集合?有没有一种方法可以将Iterable简化或者转换成其他可迭代的类型?

你好。为什么你没有将我的答案标记为正确的呢?并行流难道不比使用单个线程的流方法更快(对于更大的集合)吗? - Karol Król
部分原因是,就我的情况而言,根据https://dev59.com/2GIj5IYBdhLWcg3wUjvG中的解释,使用 parallelStream 对我没有优势(集合不够大)。另一方面,因为两个答案在不同情况下都正确,所以我选择了更简单的答案。 - Pace
4个回答

10

如果你只想迭代 Stream 的元素,无需将其收集到 Collection 中,只需使用 forEach :

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

3

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

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

通过使用更多的线程迭代集合。

为了衡量哪种流或并行流处理对于特定情况更快,请查看@Brian Goetz关于相关问题的答案:问题


2

有没有一种方法可以简单地收集一个可迭代对象或其他类型的对象,以便我可以迭代它?

如果出于某些原因您确实希望将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可能是一般情况下的“正确”方法。 java.util.stream包描述iterator描述为一个“逃生口”。

0
如果你的目标是性能,那就不要使用流。流很好用,但几乎总是比普通的Java迭代慢。
最快的方式取决于具体情况。如果只是为了迭代,那么ArrayList优于HashSet。遍历ArrayList最快的方法不是使用for-each循环,而是使用普通的i迭代:
int size = list.size();
for (int i = 0; i < size; i++) {
    ...list.get(i)...
}

确保在循环外部将大小读入本地变量,否则会导致多次不必要的调用list.size()。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接