IOS NSDictionary

写在前面

关于NSDictionary,是日常开发中经常用到的空间,但是关于它的实现原理,很少去研究。在这里做一个总结

字典的底层实现还是依靠HashMap,HashMap 的本质上市 数组 + 链表

HashMap

1、HashMap的实现

HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。

HashMap的主干是一个Entry数组HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。

//HashMap的主干数组,可以看到就是一个Entry数组,初始值为空数组{},主干数组的长度一定是2的次幂,至于为什么这么做,后面会有详细分析。
transient Entry[] table = (Entry[]) EMPTY_TABLE;

Entry是HashMap中的一个静态内部类。代码如下

    static class Entry implements Map.Entry {
        final K key;
        V value;
        Entry next;//存储指向下一个Entry的引用,单链表结构
        int hash;//对key的hashcode值进行hash运算后得到的值,存储在Entry,避免重复计算
    }
1024555-20161113235348670-746615111.png

如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。

2、扩容

当发生哈希冲突并且size大于阈值的时候,需要进行数组扩容,扩容时,需要新建一个长度为之前数组2倍的新的数组,然后将当前的Entry数组中的元素全部传输过去,扩容后的新数组长度为之前的2倍,所以扩容相对来说是个耗资源的操作。

HashMap的数组长度一定是2的次幂,这样可以保证在扩容后从,新的数组索引和老数组索引一致,大大减少了之前已经散列良好的老数组的数据位置重新调换,会使得获得的数组索引index更加均匀。

3、重写equals

在重写equals的方法的时候,必须注意重写hashCode方法,同时还要保证通过equals判断相等的两个对象,调用hashCode方法要返回同样的整数值。而如果equals判断不相等的两个对象,其hashCode可以相同(只不过会发生哈希冲突,应尽量避免)。

NSDictionary使用原理

了解了HashMap的原理以后,对于NSDictionary的原理和底层实现就更加容易了

1.NSDictionary(字典)是使用 hash表来实现key和value之间的映射和存储的,so , hash函数设计的好坏影响着数据的查找访问效率。

-(void)setObject:(id)anObject forKey:(id )aKey;

2.Objective-C 中的字典 NSDictionary 底层其实是一个哈希表,实际上绝大多数语言中字典都通过哈希表实现,

参考文章:[HashMap

你可能感兴趣的:(IOS NSDictionary)