哪种检查 NSDictionary 是不是包含特定键的方法更快?

Posted

技术标签:

【中文标题】哪种检查 NSDictionary 是不是包含特定键的方法更快?【英文标题】:Which method of checking to see if a NSDictionary contains a particular key is faster?哪种检查 NSDictionary 是否包含特定键的方法更快? 【发布时间】:2009-05-06 20:15:57 【问题描述】:

我可以通过两种方式测试 NSDictionary 中是否存在键:

BOOL containsKey = [[dictionary allKeys] containsObject:foo];

BOOL containsKey = ([dictionary objectForKey:foo] != nil);

哪种方法更快,为什么?

【问题讨论】:

"请展示你的作品?"您拥有与我们相同的工具。如果您想知道此类问题的答案,您应该尝试分析不同的代码。 Daniel 是绝对正确的,这是一种非常懒惰的方式来获得易于测试的问题的答案。但是我得到了一些非常好的答案和一些真实的性能结果,所以谢谢大家让我有点懒。 我知道人们对上面问题中的“请展示你的作品”这一行有点失望,但我认为堆栈溢出的目的是为了回答各种基本问题, 不?所以,澄清一下,我没有问这个,因为我不知道答案,找不到自己,或者是一个粗鲁的混蛋。相反,因为除非您熟悉 Foundation 系列,否则答案不会立即显而易见,这似乎是一个很好的问题和答案。 这个问题已经引起了我们社区的多个标志。我对您的问题进行了小幅编辑,请考虑保留它(或将我的编辑修改为任何内容,而不是原来的内容)。 我完全没有意识到我可以在事后编辑问题。 /掌脸 【参考方案1】:

哈希查找通常比遍历所有字典键、从它们创建一个数组(内存分配相对昂贵)然后搜索数组(甚至不能是二进制搜索,因为数组是未排序)。

不过,为了科学起见,我制作了两个可执行文件,每个样式只执行 100 万次并对其进行计时。

使用所有键:

real    0m4.185s
user    0m3.890s
sys     0m0.252s

使用 objectForKey:

real    0m0.396s
user    0m0.189s
sys     0m0.029s

显然,各种因素都会影响这一点——字典的大小、缓存 allKeys 返回值等。不过,我不希望出现数组搜索比字典查找更快的情况。

【讨论】:

Chuck,你能用字典中的字典来测试 valueForKey 吗?我认为除了知道 objectForKey 执行得更快之外,这将是最有用的。提前致谢。【参考方案2】:

我看不出请求 allKeys 数组如何可能更快,否则 NSDictionary 至少会在内部执行等效操作。

编辑:我想你可以构建一个 allKeys 方法会更快的情况 - 例如,通过在你的密钥的 hash 方法中花费很长时间,而不是在你的 isEqual: 方法中。你也可以为NSDictionary 交换一个疯狂的实现,它们也被交换(因为NSDictionary 是抽象的。)

【讨论】:

同意。要求 allKeys 会给你一个 NSArray,其中 containsObject 必须迭代地搜索寻找 foo。另一方面,objectForKey 将使用哈希来计算 foo 在字典中的位置,以便可以直接确定 foo 的存在。【参考方案3】:

在考虑此类性能问题时,请记住,Foundation 数据类会根据您在其中存储的对象数量来交换其底层数据结构。例如,我认为一个小的 NSArray 实际上使用哈希表进行存储,直到它达到一定的大小。

【讨论】:

哈希表不是更有可能变得更有益吗?测试 10 个左右的对象是否相等是微不足道的。虽然有几千个对象,但哈希表是一个明显的胜利。 你很可能是对的,我记得前段时间有人写了一篇关于这个的文章(连同基准测试),但从那以后我没有考虑太多。 ridiculousfish.com/blog/posts/array.html 将是您正在考虑的帖子

以上是关于哪种检查 NSDictionary 是不是包含特定键的方法更快?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 NSDictionary 中的值是不是存在于字典数组中

如何检查表是不是包含特定列?

如何检查 int var 是不是包含特定数字

检查 NSMutableString 是不是不包含特定字符

如何检查元素是不是包含特定的类属性

Bash:检查目录是不是仅包含具有特定后缀的文件