【问题标题】:What's wrong with using NSObject's hash to create an NSMutableDictionary key?使用 NSObject 的哈希创建 NSMutableDictionary 键有什么问题?
【发布时间】:2011-05-18 21:04:40
【问题描述】:

在一些地方,我需要对象到对象的映射,并使用 NSMutableDictionary 作为查找表。密钥是一个装箱的 NSObject 哈希,例如:

  [dict setObject:newObject forKey:[NSNumber numberWithUnsignedInt:[keyObject hash]]];

其中 keyObject 是自定义类的实例,它按原样继承 NSObject 的 - (NSUInteger)hash 实现。我在其他地方保留了对 keyObject 的引用,因此我可以使用它来获取 newObject:

[dict objectForKey:[NSNumber numberWithUnsignedInt:[keyObject hash]]]

到目前为止,这似乎有效,尽管相关应用还很年轻。

不过,Matt Gallagher 写过这种方法:

(don't laugh, I've seen it done)

这稍微削弱了我的信心(因为这是一个 iOS 应用程序,我不能使用他建议的 NSMapTable)。

谁能指出以这种方式使用 NSObject 的哈希有什么问题,以及对于 iOS 应用程序的简单对象-对象映射有什么更好的方法?

【问题讨论】:

    标签: objective-c ios


    【解决方案1】:

    除了散列的非唯一性之外,如果您像这里所做的那样将它们硬塞到unsigned int 中,您实际上已经保证即使是直接返回对象指针的-hash 方法也不一定会产生在一个唯一的键中。

    如果您打算这样做,那么与其使用NSNumber,不如至少使用NSValue+valueWithPointer:-pointerValue 方法。

    如果你真的想要一个NSDictionary 接口并且由于某种原因不能使用NSMapTable,你可以使用Core Foundation 来创建一个以原始对象指针作为键的字典。如果你这样做,你甚至可以选择内存管理如何为你用作字典中的键的对象工作;例如,您可能想要保留键,您可能想要复制键,或者您可能决定只关心指针值本身。

    【讨论】:

    • “鞋拔子”?在 iOS 上,sizeof(NSUInteger) == sizeof(unsigned int)
    • @Josh Caswell:On iOS, sizeof(NSUInteger) == sizeof(unsigned int) 虽然目前可能是这样,但NSValuevalueWithPointer: 不是更清楚地表明意图吗?
    • @drewk:我认为使用地址是正确的方法,+[NSValue valueWithPointer:] 是一个很好的方法。我只是想指出 alastair 的回答似乎错误地指的是 OS X。
    • @alistair:NSObject 的散列返回一个 NSUInteger(没有鞋拔要求)。我走这条路是因为在 iOS 上我没有 NSMapTable 可用。 CF 路线在某些时候可能很诱人,尽管我现在对 CF 还不够熟悉。
    • @drewk, @josh:带有指针值的 NSValue 看起来不错。
    【解决方案2】:

    哈希不保证是唯一的。

    【讨论】:

    • NSObject 的默认实现只是返回它的内存位置,我想。这应该足以在实例的生命周期内指定实例相等性。
    • 如果直接使用对象的内存位置呢?那么其他人实现不同的hash 方法就没有关系了。
    • 是的,我能做到。但无论哪种方式,这正是 MG 在我链接到的帖子中所嘲笑的。他清楚地看到以这种方式使用盒装内存地址作为键有什么问题(或至少很有趣),我想知道为什么。还有什么是在 obj c 中假装关联数组的更好方法。
    • 也许他觉得尴尬的是拳击?可能有更好的方法,但我认为使用内存地址没有任何问题。 (我仍然会避免使用hash,因为我们无法控制被覆盖的行为。)
    • @Cris:我同意 Jon 的评论。阅读博客文章,我不认为 Matt 说不应该这样做,只是对于现在通过NSMapTable 的可用性解决的问题来说,这是一种尴尬的解决方法。直接使用地址,而不是依赖hash 来不被覆盖;对象的地址必须是唯一的,所以它应该可以很好地用作键。有趣的问题,顺便说一句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-25
    • 2011-04-27
    • 2013-12-30
    • 2016-09-19
    • 2015-10-25
    • 1970-01-01
    相关资源
    最近更新 更多