NSDictionary 的内部实现
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 的内部实现的更多相关文章
- 非等高cell实战(01)-- 实现微博页面
非等高cell实战(01)-- 实现微博页面 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战来整合一下. 首先看一下效果图: 需求分析 此页面为非等 ...
- (转)ios error:unrecognized selector sent to class
转自:http://blog.itpub.net/12231606/viewspace-1081952/ 今天将app统计的.a静态库包含到一个app应用中,调试时报下面的错误: *** Termin ...
- 非等高cell实战--实现微博页面
代码地址如下:http://www.demodashi.com/demo/11639.html 前言 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战 ...
- iOS - error:unrecognized selector sent to class 导入第三方SDK .a后不识别,运行崩溃
今天将app统计的.a静态库包含到一个app应用中,调试时报下面的错误: *** Terminating app due to uncaught exception 'NSInvalidArgumen ...
- KVO内部实现原理
KVO的原理: 只要给一个对象注册一个监听, 那么在运行时, 系统就会自动给该对象生成一个子类对象, (格式如:NSKVONotifying_className), 并且重写自动生成的子类对象的被监听 ...
- KVO的内部实现原理
kvo概述 kvo,全称Key-Value Observing,它提供了一种方法,当对象某个属性发生改变时,允许监听该属性值变化的对象可以接受到通知,然后通过kvo的方法响应一些操作. kvo实现原理 ...
- OC:属性的内部实现原理、dealloc内释放实例变量、便利构造器方法的实现原理、collection的内存管理
代码: // // main.m #import <Foundation/Foundation.h> #import "Person.h" #import " ...
- NSDictionary所有API的学习。
<欢迎大家增加iOS开发学习交流群:QQ529560119> @property (readonly)NSUInteger count; //1.利用指定的key寻找相应的value - ...
- NSDictionary实现原理-ios哈希hash和isEqual
NSDictionary实现原理-ios哈希hash和isEqual OC中自定义类的NSCopying实现的注意事项(isEqual & hash实现) http://blog.csdn ...
随机推荐
- django 学习笔记(一)搭建基础环境
1.安装django 下载地址 https://github.com/django/django 解压后进入文件夹运行指令 >> python setup.py install 2.创建工 ...
- ECMAScript6之Set结构和Map结构
set数据结构 ES6提供了一个新的数据结构,Set,Set和Array数组相似,但是Set里没有重复的数据,可以说是一个值的集合. 同时,Set数据结构有以下属性和方法: size:返回成员总数 a ...
- ubuntu下update-alternatives命令的使用
在ubuntu系统中,update-alternatives是专门维护系统命令链接符的工具,其可以对某个工具的多个软件版本进行管理,通过它可以很方便的设置系统默认使用哪个命令的哪个软件版本. 在命令行 ...
- THINKCMF-NGINX伪静态
location / { index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^/index.php( ...
- js字符串操作
javascript中字符串常用操作总结.JS字符串操作大全 String对象属性 (1) length属性 length算是字符串中非常常用的一个属性了,它的功能是获取字符串的长度.当然需要注意的是 ...
- [O]打印时闪退问题
1. 使用的是Office批量打印精灵1.2版,软件可以打开 2. Win8.1 MSDN原版操作系统,系统重装了,.NET Framework也装了 3. 使用真实打印机打印,打印时闪退,没有任何提 ...
- mysql 时间类型分类
MySQL:MySQL日期数据类型.MySQL时间类型使用总结 MySQL 日期类型:日期格式.所占存储空间.日期范围 比较. 日期类型 存储空间 日期格式 日期范围------------ ---- ...
- Gentoo双网卡同时启用上内外网
引言:本文配置网络通过 OpenRC/netifrc 方法(net.*scritps)配置. 外网网卡:enp3s4 内网网卡:enp2s0 外网地址(通过路由器) IP: 192.168.1.10 ...
- django模板 实现奇偶分行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vga显示彩条
vga显示驱动程序可分为扫描行列和行列同步两个部分 //注意:只有在有效区域内给vga赋值才会有颜色变化 assign vga_b = isready ? vga_s[:] :'d0; assign ...