我们应该如何为空值管理 jdk8 流
我知道这个主题可能有点 提前
因为 JDK8 尚未发布(而且目前还没有发布..)但我正在阅读一些关于 Lambda 表达式的文章,尤其是部分与称为 Stream 的新集合 API 相关.
I know the subject may be a bit in advance
as the JDK8 is not yet released (and not for now anyway..) but I was reading some articles about the Lambda expressions and particularly the part related to the new collection API known as Stream.
这是 Java 杂志文章中给出的示例(它是一种水獭种群算法..):
Here is the example as given in the Java Magazine article (it is an otter population algorithm..):
Set<Otter> otters = getOtters();
System.out.println(otters.stream()
.filter(o -> !o.isWild())
.map(o -> o.getKeeper())
.filter(k -> k.isFemale())
.into(new ArrayList<>())
.size());
我的问题是,如果在 Set 内部迭代过程中,其中一只水獭为空,会发生什么?
My question is what happen if in the middle of the Set internal iteration, one of the otter is null?
我希望抛出 NullPointerException,但也许我仍然停留在以前的开发范式(非功能性)中,有人可以告诉我应该如何处理吗?
I would expect a NullPointerException to be thrown but maybe am I still stuck in the previous development paradigm (non-functional), can someone enlighten me as how this should be handled?
如果这真的抛出 NullPointerException,我觉得这个功能很危险,只能按如下方式使用:
If this really throw a NullPointerException, I find the feature quite dangerous and will have to be used only as below:
- 开发人员确保没有空值(可能使用以前的.filter(o -> o != null))
- 开发者确保应用永远不会生成 null otter 或特殊的 NullOtter 对象来处理.
什么是最好的选择,或任何其他选择?
What is the best option, or any other option?
推荐答案
目前的想法似乎是容忍"空值,即一般允许它们,尽管有些操作的容忍度较低,最终可能会抛出 NPE.请参阅 对空值的讨论在 Lambda 库专家组邮件列表中,特别是 这条消息.随后出现了围绕选项 #3 的共识(Doug Lea 提出了明显的反对意见).所以是的,OP 对 NPE 导致管道爆炸的担忧是有道理的.
Current thinking seems to be to "tolerate" nulls, that is, to allow them in general, although some operations are less tolerant and may end up throwing NPE. See the discussion of nulls on the Lambda Libraries expert group mailing list, specifically this message. Consensus around option #3 subsequently emerged (with a notable objection from Doug Lea). So yes, the OP's concern about pipelines blowing up with NPE is valid.
Tony Hoare 将 null 称为 "十亿美元的错误." 处理空值是一种真正的痛苦.即使使用经典集合(不考虑 lambda 或流),空值也是有问题的.正如评论中提到的 fge ,一些集合允许空值,而其他集合则不允许.对于允许空值的集合,这会在 API 中引入歧义.例如,使用 Map.get(),返回 null 表示 key 存在且其值为 null,或者 key 不存在.人们必须做额外的工作来消除这些情况的歧义.
It's not for nothing that Tony Hoare referred to nulls as the "Billion Dollar Mistake." Dealing with nulls is a real pain. Even with classic collections (without considering lambdas or streams) nulls are problematic. As fge mentioned in a comment, some collections allow nulls and others do not. With collections that allow nulls, this introduces ambiguities into the API. For example, with Map.get(), a null return indicates either that the key is present and its value is null, or that the key is absent. One has to do extra work to disambiguate these cases.
null 通常用于表示没有值.针对 Java SE 8 提出的处理此问题的方法是引入一个新的 java.util.Optional
类型,它封装了一个值的存在/不存在,以及提供默认值、抛出异常、调用函数等行为.如果该值不存在.Optional
只被新的 API 使用,但是,系统中的其他所有东西仍然必须忍受 null 的可能性.
The usual use for null is to denote the absence of a value. The approach for dealing with this proposed for Java SE 8 is to introduce a new java.util.Optional
type, which encapsulates the presence/absence of a value, along with behaviors of supplying a default value, or throwing an exception, or calling a function, etc. if the value is absent. Optional
is used only by new APIs, though, everything else in the system still has to put up with the possibility of nulls.
我的建议是尽可能避免实际的空引用.鉴于如何可能存在空"水獭,从示例中很难看出.但如果有必要,OP 建议过滤掉空值,或将它们映射到哨兵对象(Null对象模式)是很好的方法.
My advice is to avoid actual null references to the greatest extent possible. It's hard to see from the example given how there could be a "null" Otter. But if one were necessary, the OP's suggestions of filtering out null values, or mapping them to a sentinel object (the Null Object Pattern) are fine approaches.
相关文章