iOS NSDictionary除了NSString 类型外还有什么类型可以作为key

在iOS中,只要是不为nil的OC不可变对象类型都可以作为NSDictionary<KeyType, ObjectType>的KeyType。比如NSNumber,NSArray,NSMutableArray,NSDictionary等等。但是自定义对象作为key的时候必须遵守<NSCopying>协议并实现其协议方法- (id)copyWithZone:(NSZone *)zone,如下:

- (id)copyWithZone:(NSZone *)zone{
    //这里必须是self本身对象,具体原因请下翻
    return self;
}

一、探究

  • 首先任意对象可以作为NSDictionary的Value。这个我相信大家已经熟烂于心。所以下边的示例中,NSDictionary的Value我只用了一个字符串。

  • NSNumber作为Key进行试验


    NSNumber.png
  • NSArray作为Key进行试验


    NSArray.png
  • NSDictionary作为Key进行试验


    NSDictionary.png
  • NSMutableArray作为Key进行试验


    NSMutableArray.png
  • 自定义对象作为Key进行试验(记得实现<NSCopying>的copyWithZone

    image.png

二、原理

  • NSDictionary苹果系统实现原理

Objective-C 中的字典 NSDictionary 底层其实是一个哈希表,实际上绝大多数语言中字典都通过哈希表实现。
NSDictionary是使用 hash表来实现key和value之间的映射和存储的, hash函数设计的好坏影响着数据的查找访问效率。数据在hash表中分布的越均匀,其访问效率越高。而在Objective-C中,通常都是利用NSString 来作为键值,其内部使用的hash函数也是通过使用 NSString对象作为键值来保证数据的各个节点在hash表中均匀分布。
字典每个条目存取是通过将字典的键(Key)计算出键的hash值,通过查hash表获取具体的value。所以作为NSDictionary 的键(Key)取值的时候,只要其key对象内容地址相同就可以取出相应的值。(PS:地址不同,对象相同的遵守<NSCopying>协议的key也可以取出对应的value)。

  • 从官方文档一些细节中体现

- (void)setObject:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey

从这个方法中可以知道, 要作为 Key 值,必须遵循 NSCopying 协议。也就是说在NSDictionary内部,会对 aKey 对象 copy 一份新的。而 anObject 对象在其内部是作为强引用(retain或strong)。所以在MRC下,向该方法发送消息之后,我们会向anObject发送 release 消息进行释放

三、注意事项

1.自定义对象作为key必须遵守<NSCopying>协议并实现其协议方法- (id)copyWithZone:(NSZone *)zone . 切记 切记 切记!

- (id)copyWithZone:(NSZone *)zone{
    
    return self;
}

2.尽量使用NSString

  • 一般来说,如果你用苹果的plist来储存文件的话,那么key只能是NSString格式,使用NSNumber格式的话,-writeToFile是写不进去的,会返回值NO
  • Classes such as NSString that are part of Foundation have a good hash function.

3.苹果的官方文档(部分摘要)指出:

A key can be any object that adopts the NSCopying protocol and implements the
 hash and isEqual: methods.

If the key objects have a good hash function, accessing an element, 
setting an element, and removing an element all take constant time. With a poor
hash function (one that causes frequent hash collisions), these operations 
take up to linear time. Classes such as `NSString` that are part of Foundation 
have a good hash function.
笔者拙劣的翻译:

OC对象作为字典的Key需要遵守NSCopying协议并且实现hashisEqual两个方法。

如果有一个好的hash性能的OC对象作为字典的Key,当访问、修改、移除一个条目所耗费的时间都是基本固定的。如果作为key的对象的hash性能很低(就是hash值经常冲突),上边那些操作所耗费的时间将呈先行增长。举个例子来说,Foundation 框架中的NSString的hash性能就很不错。

  • 上边我提到的说是必须(注意是必须)遵守协议<NSCopying>并实现(id)copyWithZone:(NSZone *)zone。这是保证程序不会一运行就crash。更完备性的就是如官网文档第三段所说将isEqualhash两个方法一起重写。
  • NSDictionary苹果官网链接

4.有些朋友可能阅读上边例子的时候对 @[] 或者@{}作为Key会有一些疑问

@[]、@{}、@3 这三个快捷类型在内存中的地址只有一份。所以上边可以正常的取出值。


地址一样

如果您有什么疑问或者书写歧义,非常感激您能留言~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 一、深复制和浅复制的区别? 1、浅复制:只是复制了指向对象的指针,即两个指针指向同一块内存单元!而不复制指向对象的...
    iOS_Alex阅读 1,355评论 1 27
  • 这是昨天的题目,当时想写别的。今天特别想补回来,特别喜欢这个题目,喜欢这个"情味",情感与生活里的味道。 这是需要...
    何偀阅读 717评论 0 1
  • 基础造型
    写作的沐阳爱画画阅读 344评论 8 10
  • 我是一个和尚,一个修行的和尚。 我出生于民国二年,今年已经六十岁了,二十岁那年,我还是个翩翩公子的时候,遇到了一个...
    鸣音阅读 431评论 1 1
  • 去年第一次听到这首歌就泪目~除了感动,惊讶于如此相似…… 最早去的小酒馆在芳沁路,6年前我上班的公司曾在那楼上,门...
    大Z小姐阅读 276评论 0 2