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 ...
随机推荐
- php学习笔记——基础知识(2)
9.PHP语句 if 语句 - 如果指定条件为真,则执行代码 if...else 语句 - 如果条件为 true,则执行代码:如果条件为 false,则执行另一端代码 if...else if.... ...
- 自动生成 Makefile (automake/autoconf 入门)
作为Linux 下的程序开发人员,大家一定都遇到过Makefile ,用make 命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Makefile ,如果要想写出一个符合自由软件 ...
- DB2数据库实例创建与删除 学习笔记
以root身份执行 $DB2HOME/instance/db2idrop -f 实例名,注意一定要加-f,否则不会删除实例下面sqllib文件.如果不幸忘了,执行db2icrt,会报sqllib文件存 ...
- Thrift学习记录
Thrift学习记录 Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在C++,Java,Python,PHP,Ruby,Erlang, ...
- MySQL数据库安装(CentOS操作系统/tar.gz方式)
1. 上传Mysql安装包“mysql-5.5.40-linux2.6-x86_64.tar.gz”到部署机,位置任意: 2. 将Mysql安装包解压到其所在目录,命令如下: -linux2.-x86 ...
- ElasticSearch(8)-分布式搜索
分布式搜索的执行方式 在继续之前,我们将绕道讲一下搜索是如何在分布式环境中执行的. 它比我们之前讲的基础的增删改查(create-read-update-delete ,CRUD)请求要复杂一些. 注 ...
- centos php 扩展安装
1. 安装mysqli扩展 1.进入php源代码目录:# cd /home/apps/web/php/php-5.3.5/ 2.再进入要添加的mysqli扩展源码目录:# cd ext/mysqli/ ...
- js便利关联数组 及数组定义方式 分类
"http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=& ...
- 在windows下安装pip scrapy...
将 C:\Users\用户名\AppData\Local\Programs\Python\Python35\Scripts C:\Users\用户名\AppData\Local\Programs\Py ...
- select空间提交form表单传递参数
如下, 到了 <form name="modelForm" action="/portal/defectinfo/toDefectPage?projectname= ...