笔者自语: 当有一个面试官问我NSDictionary底层实现原理,我平时开发的时候只是会用而已,哪里知道它的内部实现原理呀,一脸懵逼的样子,感受跟那个面试的人相差甚远,如今有空来系统整理一下我本身对NSDictionary内部实现原理的理解,真的理解了对你只有好处没有坏处,永远不要说我会用就完了,那只是初级开发工程师的要求不是吗?废话很少说,但愿各位引发重视。面试
一言以蔽之: 在OC中NSDictionary是使用hash表来实现key和value的映射和存储的。算法
那么问题来了什么是hash表呢?数组
哈希表(hash表):又叫作散列表,是根据关键码值(key value)而直接访问的数据结构。也就是说它经过关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射叫作函数,存放记录的数组叫作哈希表。数据结构
读到此处咱们获得一个关键信息:所谓哈希表就是一个数组,数组中每个元素称为一个箱子(bin),箱子中存放的是键值对。看一个示意图就一目了然了:函数
hash表存储过程简单介绍:cdn
依此咱们得出结论: OC中的字典实际上是一个数组,数组中每个元素一样为一个链表实现的数组,也就是数组中套数组。对象
那么对应在oc中字典是如何进行存储的呢?blog
在oc中每个对象建立时,都默认生成一个hashCode,也就是通过hash算法生成的一串数字,当利用key去取字典中的value时,如果使用遍历或者二分查找等方法,效率相对较低,因而出现了根据每个key生成的hashCode将键值对放到hasCode对应的数组中的指定位置,这样当用key去取值时,便没必要遍历去获取,既能够根据hashCode直接取出。由于hashCode的值过大,或许通过取余获取一个较小的数字,假如是对999进行取余运算,那么获得的结果始终处于0-999之间。可是,这样作的弊端在于取余所获得的值,多是相同的,这样可能致使彻底不相干的键值对被新的键值对(取余后值key相等)所覆盖,因而出现了数组中套链表实现的数组。这样,key值取余获得值相等的键值对,都将保存在同一个链表数组中,当查找key对应的值时,首先获取到该链表数组,而后遍历数组,取正确的key所对应的值便可。开发
至此NSDictionary的底层原理算是基本上讲透彻了,但愿对看到者有必定的启示做用,那么笔者就心满意足了。hash