NSDictionary實現原理-ios雜湊hash和isEqual

來源:互聯網
上載者:User

標籤:nslog   ict   tin   fork   atomic   dom   sel   節點   協議   

NSDictionary實現原理-ios雜湊hash和isEqual OC中自訂類的NSCopying實現的注意事項(isEqual & hash實現)http://blog.csdn.net/linshaolie/article/details/41494303 iOS開發 之 不要告訴我你真的懂isEqual與hash!http://m.blog.csdn.net/hx_lei/article/details/53885798http://www.jianshu.com/p/915356e280fc 

       NSDictionary(字典)是使用 hash表來實現key和value之間的映射和儲存的, hash函數設計的好壞影響著資料的尋找訪問效率。資料在hash表中分布的越均勻,其訪問效率越高。而在Objective-C中,通常都是利用NSString 來作為索引值,其內部使用的hash函數也是通過使用 NSString對象作為索引值來保證資料的各個節點在hash表中均勻分布。

見NSDictionary中最常用的一個方法原型:

 

[objc] view plain copy 
  1. - (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;  

 

從這個方法中可以知道, 要作為 Key 值,必須遵循 NSCopying 協議。這是因為在NSDictionary內部,會對 aKey 對象 copy 一份新的。而  anObject 對象在其內部是作為強引用(retain或strong)。 

既然知道了作為 key 值,必須遵循 NSCopying 協議,說明除了 NSString 對象之外,我們還可以使用其他類型對象來作為 NSDictionary 的 key值。不過這還不夠,作為 key 值,該類型還必須繼承於 NSObject 並且要重載一下兩個方法:

 

[objc] view plain copy 
  1. - (NSUInteger)hash;  
  [objc] view plain copy 
  1. - (BOOL)isEqual:(id)object;  
  其中,hash 方法是用來計算該對象的 hash 值,最終的 hash 值決定了該對象在 hash 表中儲存的位置。我們重寫hash方法是因為每向NSDictionary和NSSet中存入一個key-value,字典會先利用即將插入的key的hash和字典中已經存在的所有的key.hash進行比較,最終來決定是新增一個key,還是覆蓋原有的key。 但是僅僅使用key.hash比較,有時會出現2個對象hash相同的情況,這時候就需要調用isEqual 方法來最終裁定,2個key對象是否相同。  OC中自訂類的NSCopying實現的注意事項(isEqual & hash實現)http://blog.csdn.net/hxmcnu/article/details/52029097 

在OC中,如果自訂類,則要考慮賦值、持久化儲存、儲存到其它容器中等各種情況的對象複製和比較,下面是一個比較全面的自訂例子,在此僅作記錄:

自訂類:

KeyValuePairs.h:

 

[objc] view plain copy 
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface KeyValuePairs: NSObject <NSCopying>  
  4. @property (nonatomic,strong)NSString *identifier;  
  5. @property (nonatomic,strong)NSString *name;  
  6.   
  7. @end  
KeyValuePairs.m:

 

[objc] view plain copy 
  1. #import "KeyValuePairs.h"  
  2.   
  3. @implementation KeyValuePairs  
  4.   
  5. - (id)copyWithZone:(NSZone *)zone  
  6. {  
  7.     KeyValuePairs *kvp = [[[self class] allocWithZone:zone] init];  
  8.     kvp.identifier = self.identifier;  
  9.     kvp.name = self.name;  
  10.     return kvp;  
  11. }  
  12.   
  13. - (BOOL)isEqualToKeyValuePairs:(KeyValuePairs *)kvp{  
  14.     if (!kvp) {  
  15.         return NO;  
  16.     }  
  17.     BOOL haveEqualName = (!self.name && !kvp.name) || [self.name isEqualToString:kvp.name];  
  18.     BOOL haveEqualIdentifier = (!self.identifier && !kvp.identifier) || [self.identifier isEqualToString:kvp.identifier];  
  19.       
  20.     return haveEqualName && haveEqualIdentifier;  
  21. }  
  22.   
  23. #pragma mark -NSObject  
  24. -(BOOL)isEqual:(id)object{  
  25.     if (self == object) {  
  26.         return YES;  
  27.     }  
  28.     if (![object isKindOfClass:[KeyValuePairs class]]) {  
  29.         return NO;  
  30.     }  
  31.     return [self isEqualToKeyValuePairs:(KeyValuePairs *)object];  
  32. }  
  33.   
  34. - (NSUInteger)hash {  
  35.     return [self.name hash] ^ [self.identifier hash];  
  36. }  
  37.   
  38. @end  

 

 

測試:

 

[objc] view plain copy 
  1. NSMutableDictionary *namesWillUpdateDic = [[NSMutableDictionary alloc] init];  
  2. NSMutableArray *names = [[NSMutableArray alloc] init];  
  3. for (int i = 0; i<1000; i++) {  
  4.     NSString *name = [NSString stringWithFormat:@"%d_zhangsan",i];  
  5.     NSString *identifier = [NSString stringWithFormat:@"%d_identifier",i];  
  6.     NSString *strObj = [NSString stringWithFormat:@"%d_strObj",i];  
  7.     KeyValuePairs *kvp = [[KeyValuePairs alloc] init];  
  8.     kvp.identifier = identifier;  
  9.     kvp.name = name;  
  10.     [namesWillUpdateDic setObject:strObj forKey:kvp];  
  11.     [names addObject:kvp];  
  12. }  
  13.   
  14. for (int j = 0; j<1000; j++) {  
  15.     int index = arc4random()%1000;  
  16.     KeyValuePairs *kvp = [names objectAtIndex:index];  
  17.     NSString *strObj = [namesWillUpdateDic objectForKey:kvp];  
  18.     NSString *msg = [NSString stringWithFormat:@"index:%d,identifier:%@,email:%@,strObj:%@",index,kvp.identifier,kvp.name,strObj];  
  19.     NSLog(@"%@",msg);  
  20. }  
   注意:1、自訂類為什麼一定要實現NSCopying協議呢?這是因為通過key-value把2個對象加入到字典中,字典會對key進行copy一份的操作,而對value對象進行retain操作,如果自訂的類不實現copy協議,那麼就不能作為字典的key對象使用。2、如果自訂類不重寫isEqual則預設使用記憶體位址比較兩個對象,可能會出現意想不到的結果3、isEqual和hash方法要同時重寫,否則isEqual方法判斷將不正確   

NSDictionary實現原理-ios雜湊hash和isEqual

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.