NSDictionary and NSMutableDictionary

 

0,铺垫

做程序员早期,我对各种编程语言提供的、类似于“STL”这样的API有一种不信任感,总觉得那是把简单的事情搞复杂。

后来维护了一个项目(2004年),该项目用C++编写,用了一些STL中的vector、iterator一类的东西,首次感受到用STL实现一些基础数据结构操作的便利性。

但头脑中的不信任感并没有完全去除,在接下来的三年,由于主要使用C语言,所以依然用最底层代码自己写单、双向链表,哈希表,FIFO队列,长度自增数组。

在一次项目升级前(2006年),关于是否用C++替换C引起了争论,当时我是Linux迷,所以坚定的站在Linus Tovard这边选择了C,最终C阵营获胜,原因是:1、无切换成本。2、效率稍高。于是又失去了一次拥抱变化的机会。

这次做iOS下一个数据管理的软件处理数据缓存,既要有非常好快的单条记录访问速度,用来更新记录内容,又要能快速返回有序的子数据集。经过简单思考后,决定用NSDictionary来作为根容器缓存数据。没想到随着使用越来越深入,对它的了解越来越多,我发现已经渐渐爱上了它。。。

废话扯完,讲讲NSDictionary的一些特性(以下不区别NSDictionary和NSMutableDictionary):

 

1,NSDictionary使用Hash表实现Key/Object存储。

Hash表是一种访问速度很快的数据结构,前提是Hash函数设计合理,能够使数据在各个子节点均匀分布,这一点使用NSString对象可以保证,这是文档中的说明:

     Classes such as NSString that are part of Foundation have a good hash function.

 

2,NSDictionary对于Key和Object的处理方式不同。

setObject:(id)object forKey:(id)key 是NSDictionary常用的message接口,第一个参数是你要存储的对象,第二个参数用来生成Hash入口(一般用NSString对象)。

key必须遵从NSCopying协议,在调用时,NSDictionary会在内部创建一个具有相同内容的内存对象,并不会引用key。

object对象却不然,NSDictionary在内部对它进行了强引用(想想ARC中的strong),也就意味着两个指针指向同一个地址,所以你可以写这样的代码:

     NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];

     NSMutableArray * array = [[NSMutableArray alloc] init];

     [dict setObject:array forKey:@"kArrayValue"];

     [array addObject:@"FirstObject"];                                   

将array插入到dict后,继续修改array的内容,相当于修改dict中存储的内容。

 

3,除了NSString,还能使用其它类型的对象作为key吗?

可以,但必须继承自NSObject,并且必须重载hash和isEqual:两个消息处理接口。

hash:计算该对象的hash值,用来定位Hash表入口。所以请写一个分布均匀的hash函数。

isEqual:通过hash值定位的Hash表入口可能有多个具有相同hash值的对象,所以在访问数据时要通过这个函数来找到相等的对象。

 

4,简单后记。

除了以上三点以外,我还曾为一个问题纠结过,看下面的情况:

     NSString * key1 = @"123";

     int a = 123;

     NSString * key2 = [NSString stringWithFormat:@"%d”, a];

key1和key2有相同的内容(都是“123”),但他们是不同的对象,所以他们的hash值相同吗?如果不同就麻烦了。

好在他们的hash值是一样的,因为在NSString的文档中,搜索“hash”,你可以看到下面的话:

     If two string objects are equal (as determined by the isEqualToString: method), they must have the same hash value.

     The abstract implementation of this method fulfills this requirement, so subclasses of NSString shouldn’t override it. 

所以使用一些高级数据结构,并非一定会降低效率,但肯定会提高代码的健壮性,前提是按照要求合理的使用它。回想那些年写“单、双向链表,哈希表,FIFO队列,长度自增数组”的岁月,泪流满面。

posted @ 2013-03-11 11:03  勤劳的天蓬  阅读(779)  评论(0编辑  收藏  举报