NSDictionary是IOS中使用的一种key-value容器,参考cocotron的源代码,NSDictionary使用NSMapTable实现。

NSMapTable同样是一个key-value的容器,下面是NSMapTable的部分代码:

typedef struct {
   NSMapTable        *table;
   NSInteger                i;
   struct _NSMapNode *j;
} NSMapEnumerator;

上述结构体描述了遍历一个NSMapTable时的一个指针对象,其中包含table对象自身的指针,计数值,和节点指针。

typedef struct {
   NSUInteger (*hash)(NSMapTable *table,const void *);
   BOOL (*isEqual)(NSMapTable *table,const void *,const void *);
   void (*retain)(NSMapTable *table,const void *);
   void (*release)(NSMapTable *table,void *);
   NSString  *(*describe)(NSMapTable *table,const void *);
   const void *notAKeyMarker;
} NSMapTableKeyCallBacks;

上述结构体中存放的是几个函数指针,用于计算key的hash值,判断key是否相等,retain,release操作。

typedef struct {
   void       (*retain)(NSMapTable *table,const void *);
   void       (*release)(NSMapTable *table,void *);
   NSString  *(*describe)(NSMapTable *table, const void *);
} NSMapTableValueCallBacks;

上述存放的三个函数指针,定义在对nsmaptable插入一对key-value时,对value对象的操作。

@interface NSMapTable : NSObject {
   NSMapTableKeyCallBacks   *keyCallBacks;
   NSMapTableValueCallBacks *valueCallBacks;
   NSUInteger             count;
   NSUInteger             nBuckets;
   struct _NSMapNode  **buckets;
}

上面是NSMtabtable真正的描述,可以看出来NSMapTable是一个哈希+链表的数据结构,因此在NSMapTable中插入或者删除一对对象时

寻找的时间是O(1)+O(m),m最坏时可能为n。

O(1):为对key进行hash得到bucket的位置

O(m):遍历该bucket后面冲突的value,通过链表连接起来。

因此:NSDictionary中的key Value遍历时是无序的,至如按照什么样的顺序,跟hash函数相关。NSMapTable使用NSObject的哈希函数。

-(NSUInteger)hash {
   return (NSUInteger)self>>4;
}

上述是NSObject的哈希值的计算方式,简单通过移位实现。右移4位,左边补0.

因为对象大多存于堆中,地址相差4位应该很正常。

@implementation NSDictionary (NSKeyValueCoding)
-(id)valueForKey:(NSString*)key;
{
    if([key hasPrefix:@"@"])
        return [super valueForKey:[key substringFromIndex:1]];
    return [self objectForKey:key];
}

-(void)setValue:(id)value forKey:(NSString*)key
{
    [NSException raise:NSInvalidArgumentException format:@"%@ called on immutable dictionary %@", NSStringFromSelector(_cmd), self];
}
@end

@implementation NSMutableDictionary (NSKeyValueCoding)
-(void)setValue:(id)value forKey:(NSString*)key
{
    if(value)
        [self setObject:value forKey:key];
    else
        [self removeObjectForKey:key];
}
@end

使用setObject:ForKey时很可能因为value或者key为空导致crash,使用setValue:Forkey就不会。

NSDictionary 的内部实现的更多相关文章

  1. 非等高cell实战(01)-- 实现微博页面

    非等高cell实战(01)-- 实现微博页面 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战来整合一下. 首先看一下效果图: 需求分析 此页面为非等 ...

  2. (转)ios error:unrecognized selector sent to class

    转自:http://blog.itpub.net/12231606/viewspace-1081952/ 今天将app统计的.a静态库包含到一个app应用中,调试时报下面的错误: *** Termin ...

  3. 非等高cell实战--实现微博页面

    代码地址如下:http://www.demodashi.com/demo/11639.html 前言 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战 ...

  4. iOS - error:unrecognized selector sent to class 导入第三方SDK .a后不识别,运行崩溃

    今天将app统计的.a静态库包含到一个app应用中,调试时报下面的错误: *** Terminating app due to uncaught exception 'NSInvalidArgumen ...

  5. KVO内部实现原理

    KVO的原理: 只要给一个对象注册一个监听, 那么在运行时, 系统就会自动给该对象生成一个子类对象, (格式如:NSKVONotifying_className), 并且重写自动生成的子类对象的被监听 ...

  6. KVO的内部实现原理

    kvo概述 kvo,全称Key-Value Observing,它提供了一种方法,当对象某个属性发生改变时,允许监听该属性值变化的对象可以接受到通知,然后通过kvo的方法响应一些操作. kvo实现原理 ...

  7. OC:属性的内部实现原理、dealloc内释放实例变量、便利构造器方法的实现原理、collection的内存管理

    代码: // // main.m #import <Foundation/Foundation.h> #import "Person.h" #import " ...

  8. NSDictionary所有API的学习。

    <欢迎大家增加iOS开发学习交流群:QQ529560119> @property (readonly)NSUInteger count; //1.利用指定的key寻找相应的value - ...

  9. NSDictionary实现原理-ios哈希hash和isEqual

    NSDictionary实现原理-ios哈希hash和isEqual   OC中自定义类的NSCopying实现的注意事项(isEqual & hash实现) http://blog.csdn ...

随机推荐

  1. DOG角点检测——opencv实现

    1.原理 Difference of Gaussian(DOG)是高斯函数的差分.将两幅图像在不同参数下的高斯滤波结果相减,得到DoG图.步骤: 处理一幅图像在不同高斯参数下的DoG 用两个不同的5x ...

  2. Python中is和==的区别的

    在python中,is检查两个对象是否是同一个对象,而==检查他们是否相等. str1 = 'yangshl' str2 = 'yang' + 'shl' print('str1 == str2:', ...

  3. Servle资源注射

    Servle资源注射@WebServlet(name = "DownloadServlet",urlPatterns ="/DownloadServlet" ) ...

  4. xml动态修改 dom4j修改

    xml的动态修改需要传入的参数 xml的位置(tomcat中的发布位置).修改后的xml需要保存的位置(因为动态修改,所以建议和xml未修改前的位置相同).添加的节点的信息.或者修改的节点的信息 SA ...

  5. Android设置窗体Activity背景透明

    背景透明 style.xml <item name="android:windowBackground">@color/transparent</item> ...

  6. HDU 5884 Sort

    二分,验证. 二分$k$,然后进行验证.有一个地方需要注意一下:如果$n$个数,每次合并$k$个,最后一次不能合$k$个,那么一开始需要补$0$之后再合并才是最优的.合并的时候用优先队列合并时间复杂度 ...

  7. mysql中timestamp的自动生成与更新

    转自:mysql中timestamp的自动生成与更新 MYSQL中TIMESTAMP类型可以设定默认值,就像其他类型一样.1.自动UPDATE 和INSERT 到当前的时间:表:----------- ...

  8. Lua math库

    函数名 描述 示例 结果 pi 圆周率 math.pi 3.1415926535898 abs 取绝对值 math.abs(-2012) 2012 ceil 向上取整 math.ceil(9.1) 1 ...

  9. SQL中游标的使用--遍历数据逐行更新或删除:相当于for循环

    --------------------------------------例子1 单纯的游标-------------------------------- create TABLE Table1 ...

  10. BT 的相关资料

    1.Android中bluetooth的架构 http://blog.csdn.net/u011960402/article/details/11035947 2.Android4.0中Bluetoo ...