Java 流与迭代器

2022-09-04 07:10:58

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

它们的用途是什么?

在谷歌上,我主要找到了如何使用它们的解释和实际的例子,我已经掌握了这些解释,没有关于幕后魔力的具体内容,这是我感兴趣的。

我并不是说在实际意义上,来自一些函数式语言,我很快就弄清楚了map/filter/reduce/等,但是为什么我们需要先转换为流呢?Java已经有了迭代器。流和迭代器之间是否存在根本区别,比如一个是懒惰的,另一个不是?还是别的什么?

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


答案 1

一般来说,谈论流是一个广阔的话题。但是,我将推断出为什么您应该更喜欢流API而不是迭代器。

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

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

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

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

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

Java-8 in Action一书中也提到了:

Streams 库中的内部迭代可以自动选择并行度的数据表示和实现,以匹配您的硬件。相比之下,一旦你通过为每个迭代编写来选择外部迭代,那么你基本上就致力于自我管理任何并行性。(在实践中,自我管理意味着“有一天我们会并行化”,或者“开始涉及任务和同步的漫长而艰苦的战斗”。

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

从本质上讲,使用流API,您的生活在许多方面都变得更加轻松,但我发现最有用的是,您现在可以将更多时间放在希望代码执行的操作上,同时您可以决定并行,而无需处理低级内容。

当然,这并不是说要始终尽可能/随时使用流。相反,它陈述了在迭代器上使用流的好处。

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


答案 2

将 的方法添加到现有方法中绝对是一种可能性,因为可以为所有其他方法提供默认实现,但是此 API 更改带来了明显的缺点:StreamIterator

  • 您的流与迭代器“结合”,即使在您不需要迭代器(例如生成器流)的情况下也是如此
  • 您不会“免费”从集合中获取流 - 就像您调用需要调用的方式一样(使用迭代器的增强循环已经是这种情况)streamiterator
  • 对于原始流,您仍然需要大量的新类型,因为在迭代器中没有类似的概念。这是很难“嫁接”到迭代器上的功能。

将流与迭代器合并的总体收益看起来并不多,因此看起来API设计人员采用了一种零片方法。