Java流与迭代器

时间:2018-02-17 22:23:51

标签: java java-8 stream iterator java-stream

我一直在玩Java新的闪亮的功能部分,其中一个让我最困惑的事情就是流?

他们的用途是什么?

在谷歌上,我大多发现了如何使用它们的解释和实际例子,我已经说过,没有具体的幕后魔术,这是我感兴趣的。

我不是说在实际意义上,来自一些函数式语言我想出了map / filter / reduce / etc.相当快,但为什么我们需要先转换为流? Java已经有了迭代器。流和迭代器之间是否存在根本区别,例如一个是懒惰而另一个不是?还是别的什么?

结论:迭代器和流之间的根本区别是什么,哪些功能无法实现为迭代器的扩展,需要一个全新的类型系列?

5 个答案:

答案 0 :(得分:9)

总的来说,谈论流是一个很大的话题。但是,我将推导出为什么你应该优先于Iterators上的流API。

首先,使用流API,我们现在可以在更高的抽象级别进行编程,就像SQL查询一样,即我们表达我们想要的东西,并让库处理其余的。

其次,流操作在幕后执行它们的迭代(内部迭代),这意味着数据的处理可以并行地或以可以更优化的不同顺序完成。

另一方面,如果您决定显式迭代您的集合以执行某些计算,无论是使用迭代器还是迭代器的语法糖(增强的for循环),那么您将明确地获取集合中的项目并逐一处理它们,因此它本身就是连续的。

使用迭代器而不是流API也意味着当你想要并行或找到不同的方法来优化你的程序时,还有很多工作要做。

然而,这也意味着你花费更多的时间来处理低级别的细节,而不是只关注你希望你的程序做什么。

在Java-8 in Action书中也提到过:

  

Streams库中的内部迭代可以自动选择   一个数据表示和并行的实现来匹配你的   硬件。相比之下,一旦你选择了外部迭代   为每个人写作,然后你基本上致力于自我管理   并行性。 (在实践中自我管理意味着“一个晴朗的日子   我们将并行化“或”开始漫长而艰苦的战斗   涉及任务和同步“。)

     

Java 8需要像Collection这样的接口,但是没有迭代器,ergo   流!

基本上,使用流API,您的生活在很多方面都要容易得多,但我发现最有用的事实是您现在可以花更多的时间专注于您希望代码执行的操作,同时您可以决定并行而不处理低级别的东西。

当然,这并不是说在任何可能的地方始终使用流。相反,它说明了使用流而不是迭代器的好处。

在某些地方,使用迭代器而不是流API更合适,反之亦然。因此,明智地选择在处理集合中的数据时采用哪种方法。

答案 1 :(得分:5)

Stream方法添加到现有Iterator肯定是可能的,因为可以为所有其他方法提供默认实现,但此API更改带来了明显的缺点:

  • 即使在您不需要迭代器(例如生成器流)的情况下,您的流也会与迭代器“结合”
  • 您没有“免费”从集合中获取流 - 与调用stream的方式相同,您需要调用iterator(已经使用迭代器增强循环的情况)< / LI>
  • 您仍然需要大量原始流的新类型,因为迭代器中没有类似的概念。这就是难以“移植”到迭代器上的功能。

将流与迭代器合并的总体收益看起来并不多,所以看起来API设计师采用了干净的工作表方法。

答案 2 :(得分:4)

  

流和迭代器之间是否存在根本区别   懒惰而另一个不是吗?还是别的什么?

是的,根本区别在于内部处理流。当我们运行流时,我们所说的是我们想要所有这些东西,过滤到这个东西,在这个条件,并给我们这个结果。我们当然不会说出我们希望如何发生的 。这意味着稍后相同的源代码可以在图形卡上以任何未知的方式并行运行。我们只是希望这种情况发生。

如果我们作为程序员明确遵守我们不关心的标准,那么幕后可能会发生许多有趣的事情。这也是功能接口和一些lambda表达式背后的很多功能。我们的想法是,如果我们说我们最初并不关心,那么编译器可以解决这些问题,而不是程序如何解决它。有时,不同的计算机安排可以通过更好的并行化等不同方式更好地解决问题。

  

底线:迭代器和迭代器之间的根本区别是什么   流和什么功能不能作为扩展实现   迭代器需要一个全新的类型?

迭代器说如何解决这个问题。它需要做这个元素然后这个元素然后这个元素和编译器不能知道是否有一些深刻的,看似隐藏的原因而不是其他方式。 Streams表示你不关心,向前反复,在千种不同的处理器上,在GPU上,它并不重要。

我希望以这种方式处理每个元素。 我希望以这种方式处理一个接一个的元素。后者实际上是不必要的限制。

答案 3 :(得分:4)

在我看来,Java 8的流在概念上非常像Unix管道。您从一组特定的数据开始,过滤,操作或执行操作,直到您获得所需的确切结果。生成的代码也比使用传统结构的代码简单得多。其他人已经提到过,流是关于 what 而不是如何

我使用我的工作的一个特殊例子是刮网站。 JSoup库将CSS查询的结果公开为实现Collection的类型。现在,如果你在Java 8中使用它,你可以免费获得流。

这意味着您可以使用CSS查询选择某些标记,过滤掉您不感兴趣的某些标记,将它们转换为某个对象并将其填充到列表中:所有这些只需少量几行

完全有可能在Java 7中执行此操作,但您需要声明列表,遍历标记,具有条件语句,实例化对象,将其添加到列表中...它很容易实现有三倍的线。

没有处理实现的优点都是有效和正确的,但是在更加面向业务的方法中,它使您的代码更易读,因此更容易维护,包括其他人。老板就是这样。

另一方面,由于Java对新功能的保守方法,隐藏实现的是很多语法糖,直到你得到异常堆栈跟踪的那一刻,并且你希望你&# 39; d学习英语文学而不是软件工程。

答案 4 :(得分:1)

除了其他答案之外,我还会提出一个更为愤世嫉俗的回答。在大多数情况下,它与程序员需要做的输入量以及代码的简洁程度有关。很多语言已经支持lambdas和流。用这些语言写作的人说像#Java; Java很糟糕,因为你必须编写所有这些代码才能处理列表中的所有项目。我的语言支持函数式编程,这就是为什么它比Java好。&#34; Java不需要Streams或lambdas,没有它们就一直都可以。但它需要保持竞争力。那里有很多Java程序员,我们不喜欢我们的语言被拖累。我同意虽然它不需要Streams,但它们确实很有趣.Stinams最终导致更少的打字,你可以更快地完成工作。它的光滑,漂亮。

Streams和lambdas存在一个问题,可能需要每隔一段时间迭代一次。那就是lambdas使用最终对象和最终基元,即lambda之外的对象和基元必须是最终的。在大多数情况下,你可能能够解决这个问题,但每隔一段时间你就可以恢复迭代,因为它更容易。不要担心这一点,当它发生时你会看到它,因为你的代码不会编译。

相关问题