NSSet, NSDictionary, NSArray是Foundation框架关于集合操作的常用类, 和其他标准的集合操作库不同, 他们的实现方法对开发者进行隐藏, 只允许开发者写一些简单的代码,让他们相信这些代码有理由正常的工作.。
 
然而这样的话最好的代码抽象风格就会被打破,苹果的本意也被曲解了. 在这种情况下, 开发者寻求更好的抽象方式来使用集合,或者说寻找一种更通用的方式。
 
对于 NSSet 和 NSDictionary,打破代码抽象风格的是他们在内存中存取object的方式. 在NSSet中, objects 是被强引用的(strongly referenced), 同样NSDictionary中的keys和values也会被NSDictionary复制。如果一个开发者想要存储一个weak类型的值或者使用一个 没有实现NSCopying协议的object作为NSDictionary的key,他可能会很聪明的想到NSValue +valueWithNonretainedObject。 iOS6和OSX 10.5以后,可以分别使用和 NSSet, NSDictionary 地位相同的 NSHashTable,NSMapTable。

NSDcitionary key应该是轻量级的,通常是字符串或数字。但这个是key-to-object映射,而不是object-to-object.而NSMapTabTable更适合于我们一般所说的映射标准,它既可以处理key-to-value又可以处理object-to-object
NSMapTabTable对应object-to-object映射的应用

 
这两个类在Foundation的collection中不常用到,为了避免你慌乱无措,下面将介绍这两个类的用法。
 
NSHashTable
NSHashTable是更广泛意义的NSSet,区别于NSSet / NSMutableSet,NSHashTable有如下特性:
* NSSet / NSMutableSet是对其成员的强类型引用,这些成员被通过hash方法和isEqual方法来完成哈希和对比功能
* NSHashTable是可变的
* NSHashTable可以持有weak类型的成员变量
* NSHashTable可以在添加成员变量的时候复制成员
* NSHashTable可以随意的存储指针并且利用指针的唯一性来进行hash同一性检查(检查成员变量是否有重复)和对比操作(equal),用法如下:
    NSHashTable *hashTable = [NSHashTable hashTableWithOptions:NSPointerFunctionsCopyIn];
[hashTable addObject:@"foo"];
[hashTable addObject:@"bar"];
[hashTable addObject:@];
[hashTable removeObject:@"bar"];
NSLog(@"Members: %@", [hashTable allObjects]);
NSHashTable是根据一个option参数来进行初始化的,因为从OSX平台上移植到iOS平台上,原来OSX平台上使用的枚举类型被放弃了,从而用option来代替,命名也发生了一些变化:
 
NSHashTableStrongMemory: 等同于NSPointerFunctionsStrongMemory. 对成员变量进行强引用。这是一个默认值。如果采用这个默认值,NSHashTable和NSSet就没什么区别了。
 
NSHashTableWeakMemory: 等同于NSPointerFunctionsWeakMemory.对成员变量进行弱引用. 使用 NSPointerFunctionsWeakMemory, object 引用在最后释放的时候会被指向 NULL。
 
NSHashTableZeroingWeakMemory: 已被抛弃.使用NSHashTableWeakMemory 代替。
 
NSHashTableCopyIn: 在对象被加入集合之前进行复制 (NSPointerFunction -acquireFunction). 等同于NSPointerFunctionsCopyIn。
 
NSHashTableObjectPointerPersonality: 用指针来等同代替实际的值,当打印这个指针的时候相当于调用description方法。和NSPointerFunctionsObjectPointerPersonality等同。
 
NSMapTable
NSMapTable是对更广泛意义的NSDictionary。和NSDictionary / NSMutableDictionary相比具有如下特性:
* NSDictionary / NSMutableDictionary会复制keys并且通过强引用values来实现存储。
* NSMapTable是可变的。
* NSMapTable可以通过弱引用来持有keys和values,所以当key或者value被deallocated的时候,所存储的实体也会被移除。
* NSMapTable可以在添加value的时候对value进行复制
 
和NSHashTable类似,NSMapTable可以随意的存储指针,并且利用指针的唯一性来进行对比和重复检查。
 
用法:假设用NSMapTable来存储不用被复制(没有实现NSCopying协议)的keys和被弱引用的value,这里的value就是某个delegate或者一种弱类型。
    id delegate = ...;
NSMapTable *mapTable = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory
valueOptions:NSMapTableWeakMemory];
[mapTable setObject:delegate forKey:@"foo"];
NSLog(@"Keys: %@", [[mapTable keyEnumerator] allObjects]);
和NSHashTable类似,NSMapTable 也是根据一个option来初始化的。
NSMapTableStrongMemory
NSMapTableWeakMemory
NSHashTableZeroingWeakMemory
NSMapTableCopyIn
NSMapTableObjectPointerPersonality
Subscripting
  
看完上面几个小例子后,你可能会想 “为什么不使用object subscripting呢?”。一些激进的NSHipster估计已经开始动手写NSMapTable的subscripting category了。
 
那么为什么NSMapTable不能继承subscripting?
 
来看看下面的代码:
@implementation NSMapTable (NSHipsterSubscripting)

- (id)objectForKeyedSubscript:(id)key
{
return [self objectForKey:key];
} - (void)setObject:(id)obj forKeyedSubscript:(id)key
{
if (obj != nil) {
[self setObject:obj forKey:key];
} else {
[self removeObjectForKey:key];
}
} @end
 
注意:参数key是类型的。这对NSDictionary NSMutableDictionary来讲是非常有用的,但是我们不能臆断对NSMapTable也同样适用。我们陷入一个僵局:通过id ,我们不能利用NSMapTable实现subscripting。如果object subscripting 的代理方法放弃了 约束,那么使用NSMutableDictionary -setObject:forKeyedSubscript:的时候编译将得不到想要的结果。
 
所以说实话,对比NSMapTable所处的位置,句法的方便和快捷并不是大数人所关注的。
 
通常,记住编程不是为了让人更聪明,而是最大化抽象一个问题的能力。 NSSet and NSDictionary是非常伟大的类,他们能解决99%的问题,也无疑是用来工作的正确工具。如果,然而你的问题牵扯到上述的内存问题时候, NSHashTable 和 NSMapTable 是值得一看的。
 
本文转自Nidom的博客,原文:《NSHashtable & NSMaptable
http://www.cocoachina.com/industry/20140605/8683.html

NSDictionary和NSMaptable, NSArray,NSSet,NSOrderedSet和NSHashTable的区别的更多相关文章

  1. 用法总结:NSArray,NSSet,NSDictionary

    用法总结:NSArray,NSSet,NSDictionary Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序 ...

  2. NSArray / NSSet / NSDictory 三者的异同点

    NSArray / NSSet / NSDictory 三者的异同点 NSArray 是一个有序对象的一个集合.相当于一个队列存储,可以有重复的数进去. NSSet 比较典型的一个HASH表(集合)算 ...

  3. 【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词

    一. 字符串 API 1. NSString 用法简介 (1) NSString API 介绍 NSString 功能 : -- 创建字符串 : 使用 init 开头的实例方法, 也可以使用 Stri ...

  4. 黑马程序员——OC语言Foundation框架 (2) NSArray NSSet NSDictionary\NSMutableDictionary

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)NSArray 1>NSArray :不可变数组 ①创建方法 ...

  5. NSArray,NSSet,NSDictionary的遍历,基本使用集锦

    NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi",@"wangwu&quo ...

  6. 用法总结:NSArray,NSSet,NSDictionary-备用

    Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序集合(数组)NSSet 用于对象无序集合      (集合)NS ...

  7. IOS中数组的使用(NSArray, NSSet, NSDictionary)

    一.Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序集合(数组)NSSet 用于对象无序集合(集合) NSDic ...

  8. NSArray, NSSet, NSDictionary

    一.Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序集合(数组)NSSet 用于对象无序集合(集合) NSDic ...

  9. 速查 NSArray NSSet NSHashTable 快速遍历之速度比较

    因为NSArray中的指针并不是简单的连续存放的,所以简单的测试了Cocoa的三种集合的快速遍历(NSFastEnumeration)性能,给出简单的参考. 添加元素: [collection add ...

随机推荐

  1. MongoDB首次启动常见问题

    问题1. exception in initandlisten 29 data directory /data/db not found 问题:MongoDB默认存储路径为/data/db,这里显示没 ...

  2. yolov3测试自己的数据

    yolov3测试自己的数据 前言 上一篇我已经介绍了利用yolov3预训练权重文件(只包含卷积层)并训练 只需要进行如下编译: ./darknet detector train cfg/voc.dat ...

  3. 《ES6标准入门》(阮一峰)--11.对象的新增方法

    1.Object.is() ES5 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===).它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0.J ...

  4. 【剑指Offer】面试题28. 对称的二叉树

    题目 请实现一个函数,用来判断一棵二叉树是不是对称的.如果一棵二叉树和它的镜像一样,那么它是对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的.     1    / \   2   2 ...

  5. Gym 101158D(暴力)

    题意:给定两个长度为N的字符串,1<=N<=4000,求满足字符串1中的某个区间所有的字母种类和个数都与字符串2中的某个区间相同最长的区间长度. 分析: 1.预处理每个串字母个数的前缀和. ...

  6. springboot启动微服务项目时,启动后没有端口号信息,也访问不了

    2018-06-05 13:43:42.282 [localhost-startStop-1] DEBUG org.apache.catalina.core.ContainerBase - Add c ...

  7. Windows10 网络图标消失 连接不上网络 的解决方法

    [背景]电脑win10的,下载一个软件重启之后网络图标消失,并且无法联网. 参照此解决方法: 原因: [Windows Event Log]服务对应的注册表出现问题,导致无法正常启动,进而导致一些依赖 ...

  8. JavaWeb高级编程(下篇)

    Java标准标签库 JSP标签语法中包含一些简写可以帮助轻松编写JSP.这些简写中第一个就是taglib指令. <%@ taglib prefix="c" uri=" ...

  9. 2-Java基本数据类型和运算符

    目录 Java基本类型 Java数据类型转换 Java运算符 1.Java基本类型 1.1.boolean布尔 - 只有true和false两种值,在内存中占1bits(位),默认是false 1.2 ...

  10. C#无边框应用

    引用using System.Runtime.InteropServices; 在窗体的全局模式下输入 [DllImport("user32.dll")] public stati ...