gpt4 book ai didi

java - 在 Java 流中,peek 真的只用于调试吗?

转载 作者:IT老高 更新时间:2023-10-28 11:23:16 25 4
gpt4 key购买 nike

我正在阅读有关 Java 流的信息,并在此过程中发现新事物。我发现的新事物之一是 peek() 函数。我在 peek 上读到的几乎所有内容都表明它应该用于调试您的 Streams。

如果我有一个 Stream,其中每个 Account 都有一个用户名、密码字段和一个 login() 和 loggedIn() 方法。

我也有

Consumer<Account> login = account -> account.login();

Predicate<Account> loggedIn = account -> account.loggedIn();

为什么会如此糟糕?

List<Account> accounts; //assume it's been setup
List<Account> loggedInAccount =
accounts.stream()
.peek(login)
.filter(loggedIn)
.collect(Collectors.toList());

现在据我所知,这完全符合它的预期。它;

  • 获取帐户列表
  • 尝试登录每个帐户
  • 过滤掉任何未登录的帐户
  • 将登录的帐户收集到一个新列表中

做这样的事情有什么坏处?有什么理由我不应该继续?最后,如果不是这个解决方案,那又是什么?

这个原始版本使用.filter()方法如下;

.filter(account -> {
account.login();
return account.loggedIn();
})

最佳答案

您必须了解的重要一点是,流是由终端操作驱动的。终端操作确定是否必须处理所有元素或任何元素。所以 collect 是一个处理每个项目的操作,而 findAny 一旦遇到匹配的元素就可能停止处理项目。

count() 可以在不处理项目的情况下确定流的大小时,可能根本不处理任何元素。由于这不是在 Java 8 中进行的优化,而是将在 Java 9 中进行的优化,因此当您切换到 Java 9 并让代码依赖 count() 处理所有项目时,可能会出现意外情况。这也与其他依赖于实现的细节有关,例如即使在 Java 9 中,引用实现也无法预测结合 limit 的无限流源的大小,但没有基本限制阻止这种预测。

自从 peek允许“对每个元素执行提供的操作因为元素是从结果流中消耗的”,它不强制处理元素,但会根据终端操作的需要执行操作。这意味着如果您需要特定的处理,例如,您必须非常小心地使用它。想要对所有元素应用一个 Action 。如果保证终端操作能够处理所有项目,它就可以工作,但即便如此,您也必须确保下一个开发人员不会更改终端操作(或者您忘记了那个微妙的方面)。

此外,虽然流保证即使对于并行流也能保持某种操作组合的相遇顺序,但这些保证不适用于 peek。当收集到一个列表中时,结果列表将对有序并行流具有正确的顺序,但 peek 操作可能会以任意顺序同时被调用。

所以你可以用 peek 做的最有用的事情是找出一个流元素是否已经被处理,这正是 API 文档所说的:

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline

关于java - 在 Java 流中,peek 真的只用于调试吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33635717/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com