NSDictionary實(shí)現(xiàn)原理

NSDictionary是基于key - value 方式林说,把key映射到一個(gè)hash表中實(shí)現(xiàn)的

key

需要支持NSCopying協(xié)議禀崖,實(shí)際上不支持也可以作為key鞋吉,但在swift中就必須要支持捷兰,支持NSCopying的原因在于农渊,NSDicitionary是NSCopying的泻红,在copy一個(gè)dictionary的時(shí)候需要key是NSCopying的(不信你用一個(gè)UIImage做key也是可以正常運(yùn)行的夭禽,只要不copy)

添加key-value的時(shí)候不會(huì)對(duì)key做深復(fù)制,以下代碼打印的內(nèi)容是一樣的

NSString *key = @"key";
NSLog(@"%p",key);
NSDictionary *dic = @{key:@(1)};
NSLog(@"%p",dic.allKeys.firstObject);

所以添加非NSCopying的對(duì)象也是可以的谊路,因?yàn)閷?duì)象作為key的必要條件是對(duì)象實(shí)現(xiàn)了:

- (NSUInteger)hash;

2018.8.3更新
上面這個(gè)說(shuō)法僅限于創(chuàng)建NSDictionary的時(shí)候,如果是在NSMutableDictionary調(diào)用setObject方法,系統(tǒng)會(huì)強(qiáng)制復(fù)制一份,也就是會(huì)調(diào)用key的copyWithZone方法創(chuàng)建一個(gè)新的對(duì)象,setObject的key沒支持NSCopying的話就會(huì)崩,同理setValue的key也需要支持NSCopying

方法讹躯,而NSObject本身就已經(jīng)實(shí)現(xiàn)了這個(gè)方法,返回的是它本身的地址

如果你這樣打印:

NSObject *obj = NSObject.new;
NSLog(@"%@",obj.hash);

你會(huì)發(fā)現(xiàn)打印出來(lái)的內(nèi)容跟

NSLog(@"%@",obj);

是一樣的蜀撑,就側(cè)面證明了NSObject的默認(rèn)-hash打印的就是它本身的地址

而如果這樣打印一個(gè)NSString的話會(huì)直接崩掉挤巡。。酷麦。說(shuō)明NSString改寫了hash方法返回了基于string計(jì)算的hash矿卑,所以只要你傳入了內(nèi)容一樣的字符串都能拿到相應(yīng)的value

并且NSString是經(jīng)過特別優(yōu)化的,會(huì)經(jīng)可能的均勻hash的平均長(zhǎng)度沃饶,使hash表盡可能的小

如果你要通過key查找value母廷,需要key實(shí)現(xiàn)了:

- (BOOL)isEqual:(id)object;

同樣NSObject也實(shí)現(xiàn)了,默認(rèn)是通過對(duì)比自己的地址

value沒什么好講的糊肤,只要是個(gè)NSObject子類都行

hash表的實(shí)現(xiàn)

NSDictionary生成hash表使用的是拉鏈法琴昆,可以理解為“鏈表的數(shù)組”即:

根結(jié)構(gòu)為數(shù)組,每個(gè)元素為鏈表

添加key的時(shí)候馆揉,會(huì)把key的hash對(duì)根結(jié)構(gòu)的長(zhǎng)度取余业舍,結(jié)果作為根結(jié)構(gòu)的下標(biāo),再把key插入到下標(biāo)對(duì)應(yīng)的鏈表元素中

一般不會(huì)在這個(gè)時(shí)候排序插入升酣,而是直接插在鏈表頭部以提高性能舷暮,當(dāng)鏈表元素過多時(shí)才排序轉(zhuǎn)換成平衡二叉樹(該處理來(lái)自http://ios.jobbole.com/87716/,里面提到NSDictionary和java的HashMap實(shí)現(xiàn)類似噩茄,而HashMap是轉(zhuǎn)換成紅黑樹)

解決hash沖突

hash沖突即存在多個(gè)hash一樣的key

一般來(lái)說(shuō)拉鏈法需要涉及到解決hash沖突下面,但巧就巧在,ObjC中一般對(duì)象的hash就是它本身的地址绩聘,所以幾乎是不可能沖突的沥割,對(duì)于NSString這類重寫了hash方法的,會(huì)同時(shí)要求重寫isEqual方法凿菩。當(dāng)真的遇到hash沖突的話机杜,NSDictionary插入時(shí)會(huì)無(wú)視沖突,而在取數(shù)據(jù)時(shí)衅谷,在找到hash后會(huì)多一步通過isEqual對(duì)比是不是需要的key叉庐,如果不是就繼續(xù)往下找,一般來(lái)說(shuō)出現(xiàn)hash沖突的key都會(huì)在同一個(gè)鏈表的相鄰位置会喝,所以查找的消耗會(huì)非常的低

同時(shí)NSHashTable陡叠,NSSet,NSMapTable的實(shí)現(xiàn)都是基于拉鏈法生成的hash表

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肢执,一起剝皮案震驚了整個(gè)濱河市枉阵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌预茄,老刑警劉巖兴溜,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侦厚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡拙徽,警方通過查閱死者的電腦和手機(jī)刨沦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)膘怕,“玉大人想诅,你說(shuō)我怎么就攤上這事〉盒模” “怎么了来破?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)忘古。 經(jīng)常有香客問我徘禁,道長(zhǎng),這世上最難降的妖魔是什么髓堪? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任送朱,我火速辦了婚禮,結(jié)果婚禮上干旁,老公的妹妹穿的比我還像新娘驶沼。我一直安慰自己,他們只是感情好疤孕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著央拖,像睡著了一般祭阀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鲜戒,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天专控,我揣著相機(jī)與錄音,去河邊找鬼遏餐。 笑死伦腐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的失都。 我是一名探鬼主播柏蘑,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粹庞!你這毒婦竟也來(lái)了咳焚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庞溜,失蹤者是張志新(化名)和其女友劉穎革半,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡又官,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年延刘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片六敬。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碘赖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出觉阅,到底是詐尸還是另有隱情崖疤,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布典勇,位于F島的核電站劫哼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏割笙。R本人自食惡果不足惜权烧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伤溉。 院中可真熱鬧般码,春花似錦、人聲如沸乱顾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)走净。三九已至券时,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伏伯,已是汗流浹背橘洞。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留说搅,地道東北人炸枣。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像弄唧,于是被迫代替她去往敵國(guó)和親适肠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • NSDictionary(字典)是使用 hash表來(lái)實(shí)現(xiàn)key和value之間的映射和存儲(chǔ)的候引, hash函數(shù)設(shè)計(jì)的...
    yymyb閱讀 1,640評(píng)論 0 3
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,321評(píng)論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,089評(píng)論 1 32
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉迂猴,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,679評(píng)論 0 9
  • NSDictionary介紹 NSDictionary(字典)是使用 hash表來(lái)實(shí)現(xiàn)key和value之間的映射...
    jackyshan閱讀 8,746評(píng)論 3 21