与每个循环的标准相比,Collection.stream()。filter()。forEach()效率低下吗?


15

IntelliJ IDEA刚刚向我建议用Java 8“ forEach”调用替换以下for-each循环:

    for (Object o : objects) {
        if (o instanceof SomeObject) {
            doSomething();
        }
    }

推荐的电话如下所示:

objects.stream().filter(o -> o instanceof SomeObject).forEach(o -> doSomething());

除非我误解了Stream的基础功能如何工作,否则在我看来,使用stream是一个O(2n)操作,而不是标准for-each循环的O(n)操作。


8
您为什么认为它是O ^ 2?实际上,流是专门为(a)允许更好的语法而(b)不会引入额外开销而发明的。(实际上,它们通常通过懒惰的评估来减少开销。)
Kilian Foth,2015年

仅基于语法,它看起来像是首先迭代过滤,然后第二次遍历过滤后的对象以运行我的代码。
Mirrana 2015年

6
即使这样做,仍将是O(2 * N),即O(N),即线性而不是二次的。但是实际上,这些迭代是相互交错的,并且如果结果已知,两者都可能提前终止-这就是流的美。花15分钟阅读Java 8中的流绝对值得。作为Venkat廉写道,'Lambda表达式是门户药物到Java 8,但流真正的瘾。“”
基利安Foth

1
此外:您的循环是反模式;)
Thomas Junk

1
@ThomasJunk您能解释一下它是一种反模式吗?我不熟悉这一点。
Mirrana 2015年

Answers:


21

尽管语法暗示,Java流不会为每个语句一次遍历集合。它将整个链应用于每个元素,一次一个。

在您的情况下,流将完全像循环一样运行。取一个元素,将其与谓词对照,然后应用您的运算,然后继续进行下一个元素。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.