为什么要写这个文档?
我在重温OC的字典类型时,发现了setValue:把值设为nil之后字典中会自动删除这个关键字指向的键值对。于是,我突然有了一个想法,在字典中可以存在多个相同的变量值,但是关键字确具有唯一性,那么NSDictionary的存储中,是否key本质上是一个结构体,存储了一个key的名称和一个指向value的指针。NSDictionary存储的本质上是存储这些结构体,而不存储value呢?
不存储value的结论是通过for in循环中获得的值为关键字得出的想法。而下面的推论也是在这个代码中测试的。
我的猜想存储图:(中间有空格表示非连续存储,以链表式存储)
NSMutableDictionary前面连续的表示一开始便创建的,后面分散的表示新添加的
推论测试
推论①:1)NSDictionary中的关键字是类似C语言的数组存储的,是一片连续的内存;
2)key是附带名称的指针
测试方法: 修改for in内部代码,使其输出key和value的地址
结论:
①我们不需要去计算key和value指针的大小,但是我们可以看到每一个key和value之间的地址差是相等的。也就是说NSDictionary中的key确实是连续存储,但是value却不是链式存储。
②每个地址之间的差为16,而指针是8。说明key和value都是包含两个指针,一个指向存储内容,一个指向名称
③NSDictionary使用一块连续的内存存储键值对(跟C语言数组一样)
推论② 1) NSMutableDictionary中后加入的键值对为链式添加
2) 编译器会为字典类型创建一块内存专门用于存储指向key的指针
测试方法: 在NSMutableDictionary添加新元素前先创建新的对象,排除堆空间连续分配内存影响结果
结论:
①NSMutableDictionary的初始化键值对存储方式跟NSDictionary是一样的
②NSMutableDictionary新增加的元素确实是链式存储的
③编译器确实分配了存储key指针的内存(如果没有,那么将无法通过for in循环找到新增的key)
字典的存储图
顺带说一下,在for in中我尝试了输出key的地址(&key),结果发现都是输出同一个地址。对此我的猜测是:
在创建NSMutableDictionary后,编译器把他放进collection后再次添加新元素时,都是在这个collection里分配的
内存,所以&key很有可能是指向这个collection内存的哈希码地址。当然啦,这也只是猜测,这其中真正的实现只有
苹果才知道了