NSHashTable & NSMapTable
比起平时常用的 NSArray、NSDictionary和NSSet,NSHashTable与NSMapTable更为少见一些。
下面二者做一个简单的介绍。
NSArray & NSSet & NSHashTable
1. NSArray 与 NSSet 的区别
其实NSSet我们平时也很少遇到,大部分时间使用NSArray已经足够,那么二者有什么区别呢?
- 互异性:集合内的元素是不重复的。
- 无序性:NSSet在内存中存储方式是不连续的,而NSArray在内存中存储位置是连续的。
- 确定性:NSSet对元素的查找效率是比NSArray高的,因为它主要使用的是hash算法。查找时间稳定。
综上所述:可知NSSet适用于 不关心集合内元素的顺序,而是需要查找元素是否在集合中,且对查找的性能有要求的情况。在这种情况下,可以用NSSet代替NSArray来存储数据。同样的,Set也有一个可变类型的子类NSMutableSet。
2. NSSet 与 NSHashTable 的区别
NSHashTable是一种类似NSSet一样的集合,但是它可用的内存语义范围更广,能够对持有对象以弱引用的方式存储。NSArray和NSSet对所持有的元素都是强持有(强引用),当我们需要对持有的元素进行弱引用时,便可以考虑使用NSHashTable。
@interface NSHashTable<__covariant ObjectType> : NSObject
在初始化hashTable时,需要设置hashTable的options,有以下两种初始化方法。
- (**instancetype**)initWithOptions:(NSPointerFunctionsOptions)options capacity:(NSUInteger)initialCapacity NS_DESIGNATED_INITIALIZER;
- (**instancetype**)initWithPointerFunctions:(NSPointerFunctions *)functions capacity:(NSUInteger)initialCapacity NS_DESIGNATED_INITIALIZER;
在第一种初始化方法中,直接选择了由系统提供的几种hashTable的options,类型为NSPointerFunctionsOptions,内容如下。
**typedef** NS_OPTIONS(NSUInteger, NSPointerFunctionsOptions) {
// Memory options are mutually exclusive
// default is strong
NSPointerFunctionsStrongMemory API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (0UL << 0), // use strong write-barrier to backing store; use GC memory on copyIn
NSPointerFunctionsZeroingWeakMemory API_DEPRECATED("GC no longer supported", macos(10.5, 10.8)) API_UNAVAILABLE(ios, watchos, tvos) = (1UL << 0), // deprecated; uses GC weak read and write barriers, and dangling pointer behavior otherwise
NSPointerFunctionsOpaqueMemory API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (2UL << 0),
NSPointerFunctionsMallocMemory API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (3UL << 0), // free() will be called on removal, calloc on copyIn
NSPointerFunctionsMachVirtualMemory API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (4UL << 0),
NSPointerFunctionsWeakMemory API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0)) = (5UL << 0), // uses weak read and write barriers appropriate for ARC
// Personalities are mutually exclusive
// default is object. As a special case, 'strong' memory used for Objects will do retain/release under non-GC
NSPointerFunctionsObjectPersonality API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (0UL << 8), // use -hash and -isEqual, object description
NSPointerFunctionsOpaquePersonality API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (1UL << 8), // use shifted pointer hash and direct equality
NSPointerFunctionsObjectPointerPersonality API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (2UL << 8), // use shifted pointer hash and direct equality, object description
NSPointerFunctionsCStringPersonality API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (3UL << 8), // use a string hash and strcmp, description assumes UTF-8 contents; recommended for UTF-8 (or ASCII, which is a subset) only cstrings
NSPointerFunctionsStructPersonality API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (4UL << 8), // use a memory hash and memcmp (using size function you must set)
NSPointerFunctionsIntegerPersonality API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (5UL << 8), // use unshifted value as hash & equality
NSPointerFunctionsCopyIn API_AVAILABLE(macos(10.5), ios(6.0), watchos(2.0), tvos(9.0)) = (1UL << 16), // the memory acquire function will be asked to allocate and copy items on input
};
默认是NSPointerFunctionsStrongMemory,即内存强引用,效果和NSSet类似,会造成对持有元素的强引用。而在其后的NSPointerFunctionsWeakMemory,则是与之对应的弱引用。
NSDictionary & NSMapTable
1. NSDictionary 和 NSMapTable 的区别
与上面的 NSSet & NSHashTable 相同的,NSDictionary 和 NSMapTable 也是在对其所持有的元素的引用状态上有区别。并且,因为每个map对象有 <key, value> 两个元素,所以mapTable的options也更多,key和value都可以选择 强引用or弱引用。
初始化方法如下。
- (**instancetype**)initWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions capacity:(NSUInteger)initialCapacity NS_DESIGNATED_INITIALIZER;
- (**instancetype**)initWithKeyPointerFunctions:(NSPointerFunctions *)keyFunctions valuePointerFunctions:(NSPointerFunctions *)valueFunctions capacity:(NSUInteger)initialCapacity NS_DESIGNATED_INITIALIZER;
可以看到,第一个初始化方法中,我们可以分别设置 keyOptions 和 valueOptions。内存语义的类型选择与hashTable相同。