我正在阅读有关Java流的信息,并在不断学习中发现新事物。我发现的新peek()功能之一就是功能。我偷看的几乎所有内容都说应将其用于调试Streams。
如果我有一个Stream,其中每个帐户都有一个用户名,密码字段以及一个login()和loggingIn()方法,该怎么办。
我也有
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()
.filter(account -> { account.login(); return account.loggedIn(); })
关键要点是:
即使达到你的近期目标,也不要以意外的方式使用该API。这种方法将来可能会中断,对于将来的维护者来说也不清楚。
将其分解为多个操作是没有害处的,因为它们是不同的操作。还有就是在不明确的和意想不到的方式,如果这种特定的行为是用Java的未来版本中修改其可能的后果使用API的伤害。
使用forEach该操作将明确维护者,有一个预期中的每个元素的副作用accounts,并且正在执行某些操作,可能发生变异它。
从某种意义上说,它是更常规peek的中间操作,直到终端操作运行后才对整个集合进行操作,但forEach实际上是终端操作。这样,你可以围绕代码的行为和流程提出强有力的论据,而不是询问是否peek行为与forEach在此情况下相同。
accounts.forEach(a -> a.login()); List<Account> loggedInAccounts = accounts.stream() .filter(Account::loggedIn) .collect(Collectors.toList());