提问人:Raedwald 提问时间:1/9/2012 最后编辑:CommunityRaedwald 更新时间:1/9/2012 访问量:18279
检查 Set 是否不包含 null 的巧妙方法
Neat way to check whether a Set does not contain a null
问:
我有一个给定对象的方法。它委托给的方法要求 不包含任何 null 元素。我想在委托之前的方法中尽早检查不包含空元素的前提条件。这样做的明显代码是这样的:Set
Set
Set
public void scan(Set<PlugIn> plugIns) {
if (plugIns == null) {
throw new NullPointerException("plugIns");
} else if (plugIns.contains(null)) {
throw new NullPointerException("plugIns null element");
}
// Body
}
但这是不正确的,因为如果实现本身不允许 null 元素,Set.contains()
可能会抛出一个。在这种情况下,捕捉然后忽略会起作用,但会不优雅。有没有一种巧妙的方法来检查这个前提条件?NullPointerException
Set
NullPointerException
界面是否存在设计缺陷?如果实现可能永远不会包含 null,为什么不改为 require to always return 呢?还是有谓语?Set
Set
Set.contains(null)
false
isNullElementPermitted()
答:
5赞
Dan Hardiker
1/9/2012
#1
最简单的方法是枚举 Set 并检查 null。
public void scan(Set<PlugIn> plugIns) {
if (plugIns == null) throw new NullPointerException("plugIns");
for (PlugIn plugIn : plugIns) {
if (plugIn == null) throw new NullPointerException("plugIns null element");
}
}
评论
1赞
Raedwald
1/9/2012
简单,但复杂,这对前提条件检查不利。O(N)
1赞
Dan Hardiker
1/9/2012
引用另一个人的话:“预优化是万恶之源”。您确定这是性能瓶颈吗?鉴于你正在做的事情,我猜其他地方存在架构问题。
0赞
Raedwald
1/9/2012
我担心的不是过早的优化。一个简洁的解决方案应该是通用的,并且相当有效。每当有人在没有首先衡量性能的情况下使用,并获得快速的好处时,他们就不会进行过早的优化。programmers.stackexchange.com/questions/79946/....HashSet
Set.contains()
3赞
Matt
1/9/2012
#2
创建一个 from 并检查是否存在HashSet
plugIns
null
public void scan(Set<PlugIn> plugIns) {
if (plugIns == null) throw new NullPointerException("plugIns");
Set<PlugIn> copy = new HashSet<PlugIn>(plugIns);
if (copy.contains(null)) {
throw new NullPointerException("null is not a valid plugin");
}
}
评论
1赞
Raedwald
1/9/2012
简单,但很复杂,并创建一个新对象,这不利于前提条件检查。O(N)
1赞
Matt
1/9/2012
您每秒扫描多少次新插件?;)根据我的经验,复制或创建新集合很少是性能问题。也许你应该防止被添加在哪里(对我来说,这听起来像是你在修复别人的错误代码,除非有正当理由存在-plugin)null
plugIns
null
0赞
Raedwald
1/9/2012
我这样做不是为了解决错误的代码。我想这样做,因为最好及早发现故障。想象一下,这是一种 API 方法:我们无法控制调用代码,但可能希望提供良好的诊断。
0赞
Raedwald
1/9/2012
“您每秒扫描多少次新插件?”好点子,您的解决方案对于我的特定情况将具有足够的性能。但我也想知道我如何在其他地方进行检查,那里的性能会更重要。
0赞
Matt
1/9/2012
好的,我明白你的意思了。但是,让我们假设这是实际 API 的一部分:在这种情况下,它取决于调用方和被调用方之间的接口/合约。如果允许作为集合的一部分,你可以用一个简单的(因为我们不知道如何处理 Null-Plugins)来处理它。如果不允许在集合中,则根本不需要检查,除非您怀疑 API 有问题。恕我直言,这与个人品味有很大关系,所以没有对错之分。希望能;)null
//body
if
null
null
2赞
Bohemian
1/9/2012
#3
只需捕获抛出的 NullPointerException 并忽略它:
public void scan(Set<PlugIn> plugIns) {
if (plugIns == null) {
throw new NullPointerException("plugIns");
}
NullPointerException e = null;
try {
if (plugIns.contains(null)) {
// If thrown here, the catch would catch this NPE, so just create it
e = new NullPointerException("plugIns null element");
}
} catch (NullPointerException ignore) { }
if (e != null) {
throw e;
}
// Body
}
如果抛出,这只会产生很小的开销,但如果你不使用异常(尤其是跟踪跟踪),它实际上是相当轻量级的。
评论
0赞
unknown_boundaries
4/16/2015
你不认为你的NPE候选人更像是IllegalArgumentException的候选人吗?
评论
Set
null
else
Set
null
Set
null
contains
false