【问题标题】:Java 8 streams when and why [closed]Java 8 流式传输的时间和原因 [关闭]
【发布时间】:2021-04-08 04:13:13
【问题描述】:

我最近开始从事一个项目,他们鼓励使用流 lambda 等编写代码。基本上,函数式编程方法。虽然我发现流很有吸引力,但我对它们有一些疑问。它们如下。

  1. 性能 - 串行流真的比相应的集合更快、更具可扩展性吗?还是只因为有一天我们可能会使用 stream().parallel() 版本而更喜欢流?

  2. 内存使用 - 考虑到像 collect(toList()) 这样的终端操作通常会创建一个新对象,流是否会成为堆内存的负担?

  3. 垃圾收集 (GC) - 流是否比收集更友好?

  4. 编程范式 - 我个人认为将函数式编程风格与 OOP 混合会导致问题。

  5. 调试 - 我亲自用笔和纸来调试我的代码,而不是使用调试器(有些人可能更喜欢)。在调试方面流有多好?

  6. 操作复杂性 - 在编写日常代码(过滤分组收集映射)时,流是小菜一碟,但我发现当我必须编写复杂逻辑时,我最终会求助于旧集合基于方法,因为它更易于调整。我是唯一一个这样做的人吗?

我知道我在这里问了多个问题,但实际上它们是标题中提到的同一问题的 6 个部分。希望对这些子问题中的每一个至少有一个总结之类的答案。如果有人也可以添加一个链接来深入了解所有这些内容,那将会很有帮助。

干杯!!

【问题讨论】:

  • 几乎所有问题的答案都是“视情况而定”。流通常并不神奇,它们只应在生成的代码简单明了的地方使用,这意味着不要太复杂。
  • 1.您问这些问题是因为您确实已经学习并使用了流 API,并且发现该实现确实提出了这些问题吗? 2. 您对流 API 与集合 API 的比较有何看法?看起来像苹果和橘子。 3. 你想对答案做什么?告诉您的项目/团队负责人您不应该使用流 API 的原因?你肯定不是说 Java 设计者在引入流时犯了一个错误……

标签: java java-stream scalability


【解决方案1】:

性能 - 串行流真的比相应的集合更快、更具可扩展性吗?

没有。至少,在当前的 Stream 实现中不是平均水平。

或者只是因为有一天我们可能会使用stream().parallel() 版本而更喜欢流?

可能是的。但是,对于许多用例,使用 parallel() 的开销超过了可能的加速。

内存使用 - 考虑到像 collect(toList()) 这样的终端操作通常会创建一个新对象,流是否会成为堆内存的负担?

AFAIK,不会。内存使用量通常不会减少。

垃圾收集 (GC) - 流比收集更友好吗?

AFAIK,不。

编程范式 - 我个人认为将函数式编程风格与 OOP 混合会导致问题。

这是你的意见。

如果您坚持让您的流操作无副作用,那么应该不会有任何问题。

  • 文档建议反对流操作中的副作用。
  • 如果您依赖副作用,那是没有用的。

调试 - 我亲自用笔和纸来调试我的代码,而不是使用调试器(有些人可能更喜欢)。在调试方面流有多好?

这是一个见仁见智的问题。我个人认为这对调试没有影响。

操作复杂性 - 在编写日常代码(过滤分组收集映射)时,流是小菜一碟,但我发现当我必须编写复杂的逻辑时,我最终会求助于旧的基于集合的方法,因为它更易于调整.我是唯一一个这样做的人吗?

你不是唯一一个。另一方面,很多人使用比简单的过滤、分组、收集和映射来做更复杂的事情。您使用流的次数越多,您就越能更好地发现其他用例。但另一方面,有些人似乎想用流做一些他们可能不应该做的事情。


我最近开始从事一个项目,他们鼓励使用流 lambda 等编写代码。

这是你和团队其他成员之间的事。我认为参与您的项目团队对此的辩论不是我/我们的职责。

【讨论】:

  • 感谢@Stephen 提供如此详细的答案。我最近开始使用流,如果您可以分享实际流 API 实现的链接(源代码)。那太好了。
  • 您应该可以使用 google 找到它。搜索“ 源代码”。
【解决方案2】:

Java 流的主要好处之一是它们可以实时处理数据。例如,假设您有一个包含 1000 个数据点的数组。如果您要使用传统方法进行处理,则需要批处理。这意味着在所有项目都已处理之前,您不会获得第一个已处理项目的结果。正如您可以想象的那样,这会大大减慢速度,尤其是当您的方法是管道的一部分时。假设这个方法需要 10 分钟(证明一点的极端例子)才能完成。另外,假设这是 20 个不同过程中的第一个,每个过程花费的时间大致相同。您正在寻找 200 分钟来处理一个数组。

现在想象同样的管道,所有流程都花费相同的时间,但是您不是批处理,而是通过流式传输数据。这涉及通过函数一个一个地处理数组项。结果是,一旦您的第一个项目完成,它就可以继续进行过程中的下一个点。在我们的示例中,第一项可能会在几秒钟内完成。无需等待其他 999 条数据进行处理,它可以立即移动到链中的下一个链接。这确保了链后端的进程被阻塞的时间要短得多。

显然,这是一个理论上的例子。因此,它没有考虑线程阻塞等问题。但是,能够同时在一个集合上运行多个进程的优势仍然很大。

这也是为什么大多数 Java 流的函数都会返回一个流的原因。它们被设计为在某种管道中运行

【讨论】:

  • 感谢@Nathan Toulbert。对于这个例子。这绝对有助于创建一种关于流的好处的图片。
  • 你表现得好像我们无法在直播前做这个。
  • @NomadMaker 添加了任何语言的大多数附加功能,以便为用户提供一种“正确”的方式来做他们已经可以做的事情。这增加了诸如文档之类的好处,确保它在更新后仍然可行,以及一般支持/维护。添加了许多 Java 的 api 来替换 3rd 方 api。有时方法甚至没有改变。 Oracle(或 Sun)基本上只是拿了一个现有的 api,把它放在 jdk 中,并承诺支持它。相同的 w 已弃用 api。我们仍然可以使用它们,但我们不能(如果我们很聪明的话),因为不能保证它在更新时会起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 2012-02-09
相关资源
最近更新 更多