第一:NSArrary
1.1:集合的基本方法
1.创建集合
NSArray 是不可变数组,一旦创建完成就不能够对数组进行,添加,删除等操作
NSArray * array = [[NSArray alloc] init];
2.通过构造方法的方式创建一个NSArray
//在创建一个NSArray的时候,集合的最后一个元素一定是nil,判断nil决定集合的结尾
NSArray * array1 = [NSArray arrayWithObjects:@"one",@"two",@"three", nil];
NSArray * array2 = [[NSArray alloc] initWithObjects:@"one",@"two",number, nil];
NSArray * karray = @[@"a",@"b",@"c"];
NSString * kstr = karray[0];//访问元素位置
//数组的index时从0开始的
NSString * str = [array objectAtIndex:0];
NSLog(@"str %@",str);
//获得数组的元素个数
NSUInteger arrayCount = [array count];
// 判断数组中是否存在某个对象
BOOL isContain = [array containsObject:id];
特性:
1.数组中可以存储不同类型的对象
2.数组实际上存储的时对象的地址,同样也可以存储数组的地址
3.存储自定义的对象 (最好都给我重写 description方法)
4.数组中存储基本数据类型, (如果你要在数组中存储基本数据类型,请包装好了之后再去存 NSNumber)
5.注意不要把nil值存储到NSArray中,会导致数据丢失
1.2:数组排序:
1.使用sortedArrayUsingSelector
NSArray * array = @[@"b",@"d",@"a",@"z"];
array = [array sortedArrayUsingSelector:@selector(compare:)]; //系统自带
2.使用block方式排序
a. 降序
NSArray *tMlist = @[@4,@5,@2,@6,@3,@7,@8];
//降序序8,7,。。
NSArray *tArray = [tMlist sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *tNumber1 = (NSNumber *)obj1;
NSNumber *tNumber2 = (NSNumber *)obj2;
//因为不满足sortedArrayUsingComparator方法的默认排序顺序,则需要交换
if ([tNumber1 integerValue] < [tNumber2 integerValue])
return NSOrderedDescending;
return NSOrderedAscending;
//因为满足sortedArrayUsingComparator方法的默认排序顺序,则不需要交换
if ([tNumber1 integerValue] > [tNumber2 integerValue])
return NSOrderedAscending;
return NSOrderedDescending;
b 升序
NSArray *tMlist = @[@4,@5,@2,@6,@3,@7,@8];
//结果:升序2,4,。。
NSArray *tArray = [tMlist sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *tNumber1 = (NSNumber *)obj1;
NSNumber *tNumber2 = (NSNumber *)obj2;
//因为满足sortedArrayUsingComparator方法的默认排序顺序,则不需要交换
if ([tNumber1 integerValue] < [tNumber2 integerValue])
return NSOrderedAscending;
return NSOrderedDescending;
// 因为不满足sortedArrayUsingComparator方法的默认排序顺序,则需要交换。
// if ([tNumber1 integerValue] < [tNumber2 integerValue])
// return NSOrderedAscending ;
// return NSOrderedDescending;
}];
c 数组逆转
NSArray *tMlist = @[@4,@5,@2,@6,@3,@7,@8];
NSArray *tArray = [tMlist sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *tNumber1 = (NSNumber *)obj1;
NSNumber *tNumber2 = (NSNumber *)obj2;
//数组逆转
return NSOrderedDescending;
}];
d.数组不变
NSArray *tMlist = @[@4,@5,@2,@6,@3,@7,@8];
NSArray *tArray = [tMlist sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *tNumber1 = (NSNumber *)obj1;
NSNumber *tNumber2 = (NSNumber *)obj2;
//数组不变
return NSOrderedAscending;
}];
总结:
1.sortedArrayUsingComparator这个方法本身就是按递增的方式排序。
2.返回的返回值(NSOrderedAscending 不交换,NSOrderedSame 不交换,NSOrderedDescending 交换)。
例如:object1 < object2 返回:NSOrderedDescending 则交换(变为object2,object1),以保证安方法本身升序。返回NSOrderedAscending,两者不交换。
对于Comparator的返回值文档有下面的说明
NSOrderedAscending
The left operand is smaller than the right operand.
NSOrderedSame
The two operands are equal.
NSOrderedDescending
The left operand is greater than the right operand
如果你期望的是值小的在前而值大的在后(升序),则可以在比较的时候返回NSOrderedAscending(-1),否则,就是NSOrderedDescending(1)。
3.使用自定义对象排序 :如果你向给你自己定义的对象排序,必须根据某一个属性来排序,
//sortDescriptorWithKey 参数要的就是你对象中,要依据哪个属性来排序,你就把哪个属性的名字当成key传入
//ascending YES表示正序 NO表示倒叙
NSSortDescriptor * d1 = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
NSSortDescriptor * d2 = [NSSortDescriptor sortDescriptorWithKey:@"year" ascending:NO];
//如果你要使用多个属性进行排序,默认在前面的NSSortDescriptor优先级比较高
NSArray * descripts = @[d2,d1];
array3 = [array3 sortedArrayUsingDescriptors:descripts];
1.3:遍历数组
遍历数组的三种方式
1>普通方式:
for (int i = 0; i<array1.count; i++){
if (i ==0)
break;
}
2>将array1数组中的每个对象拿出来赋给obj然后依次打印
for (id obj in array1){
// id obj 代表数组中的对象
// 获取obj对象在数组中的索引
NSUInteger index = [array1 indexOfObject:obj];
NSLog(@"%ld--%@",index,obj);
}
3>使用Block 每次从数组中遍历一个元素后就传递给block,block也相应的执行一次
// block中的id obj对应数组中的元素,NSUInteger idx对应数组中元素的索引 BOOL用来停止遍历
[array1 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
NSLog(@"%ld--%@",idx,obj);
// 如果索引为0 立即停止遍历
if (idx ==0){
* stop = YES;
}
};
1.4:可变数组:
1.创建可变数组
NSMutableArray * array = [[NSMutableArray alloc] initWithCapacity:0];
2.数组中加入元素
[array addObject:str1];
3.指定对象插入的位置
[array insertObject:str1 atIndex:2];
4.删除 会通过对象,删除数组中所有的同一个地址的对象
[array removeObject:str1];
4.通过索引的方式删除对象,超出了数组的count值,那么就会导致异常 index beyond bounds
[array removeObjectAtIndex:0];
[array addObject:str2];
[array addObject:str3];
[array addObject:str1];
5.删除数组中所有的元素
[array removeAllObjects];
第二:NSDictionary
第一:NSDictionary
字典是以键值对的形式来存储数据 key value
字典的顺序不是按照存储时候的顺序。
字典中可以存任意数据类型
1.创建字典
NSDictionary *dic1 = [NSDictionary dictionaryWithObject:@"value" forKey:@"key"];
2.创建多个元素字典
NSDictionary *dic2 = [NSDictionary dictionaryWithObjectsAndKeys:
@"value1", @"key1",
@"value2", @"key2",
@"value3", @"key3",
@"value4", @"key4",
nil];
3.根据现有的字典创建字典
NSDictionary *dic3 = [NSDictionary dictionaryWithDictionary:dic2];
4.根据key获取value
[dic3 objectForKey:@"key3"]);
5.获取字典数量
NSLog(@"dic count :%d", dic3.count);
6.所有的键集合
NSArray *keys = [dic3 allKeys];
7.所有值集合
NSArray *values = [dic3 allValues];
1.2 可变字典
1.创建可变字典
NSMutableDictionary *mutableDic = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
@"mvalue1", @"mkey1",
@"mvalue2", @"mkey2", nil];
2.添加现有的字典数据
[mutableDic addEntriesFromDictionary:dic3];
3.添加新的键值对象
[mutableDic setValue:@"set1" forKey:@"setKey1"];
4.以新的字典数据覆盖旧的字典数据
[mutableDic setDictionary:dic2];
5.根据key删除value
[mutableDic removeObjectForKey:@"key1"];
1.3 遍历方法
1.快速遍历
for(id key in mutableDic) {
NSLog(@"key :%@ value :%@", key, [mutableDic objectForKey:key]);
}
2.枚举遍历
NSEnumerator *enumerator = [mutableDic keyEnumerator];
id key = [enumerator nextObject];
while (key) {
NSLog(@"enumerator :%@", [mutableDic objectForKey:key]);
key = [enumerator nextObject];
}
3.根据key数组删除元素
[mutableDic removeObjectsForKeys:keys];
4.删除所有元素
[mutableDic removeAllObjects];
第三:NSSet 集合
1> NSSet是一组单值对象的不可变集合,集合中元素没有顺序;
2> 操作包括:搜索、添加、删除集合中的元素(仅用于可变集合)、比较两个集合,计算两个集合的交集和并集等。
3> 获取元素个数:集合名.count
1.1、NSSet集合常用方法(部分)
1.构造方法
+ (instancetype)setWithObjects:obj1, obj2, ..., nil;
2.使用一系列对象初始化新分配的集合:
- (instancetype)initWithObjects:(const id [])objects count:(NSUInteger)cnt;
3.确定集合是否包含anObject对象:
- (BOOL)containsObject:(id)anObject;
4.使用member:访问集合中的某一对象,有就返回此元素,没有就返回null:
- (id)member:(id)object;
5.为集合中的所有对象返回一个NSEnumerato对象:
- (NSEnumerator *)objectEnumerator;
6.确定receiver的每个元素是否都出现在otherSet中:
- (BOOL)isSubsetOfSet:(NSSet *)otherSet;
7.确定是否receiver中至少一个元素出现在对象otherSet中:
- (BOOL)intersectsSet:(NSSet *)otherSet;
8.确定两个集合是否相等:
- (BOOL)isEqualToSet:(NSSet *)otherSet;
1.2,NSMutableSet
NSMutableSet是NSSet的子类,是可变集合;
常用方法(部分):
1.创建新集合,使其具有存储numItems个元素的初始空间:
+ (instancetype)setWithCapacity:(NSUInteger)numItems;
2.将新分配的集合设置为numItems个元素的存储空间:
- (instancetype)initWithCapacity:(NSUInteger)numItems;
3.将对象object添加到集合中:
- (void)addObject:(id)object;
4.从集合中删除对象:
- (void)removeObject:(id)object;
5.删除集合中所有对象:
- (void)removeAllObjects;
6.将对象otherSet的所有元素添加到接收者:
- (void)unionSet:(NSSet *)otherSet;
7.从接收者中删除otherSet的左右元素:
- (void)minusSet:(NSSet *)otherSet;
8.从接受者中的所有不属于otherSet的元素删除:
- (void)intersectSet:(NSSet *)otherSet;
第四:集合的相互转换
//1.NSArray 转换成 NSMutableArray
NSArray * array = @[@"one",@"two",@"three"];
NSMutableArray * muArray = [NSMutableArray arrayWithArray:array];
NSLog(@"muarray %@",muArray);
//2.NSDictonary 转换成 NSMutableDictionary
NSDictionary * dic = @{@"one":@"1",@"two":@"2"};
NSMutableDictionary * muDic = [NSMutableDictionary dictionaryWithDictionary:dic];
NSLog(@"mudic %@ ",muDic);
//3.NSset 转换成 NSMutableSet
NSSet * set = [[NSSet alloc] initWithObjects:@"one",@"two", nil];
NSMutableSet *muSet = [NSMutableSet setWithSet:set];
NSLog(@"muSet %@",muSet);
//4.NSArray 转换成NSSet
NSMutableSet * muSet2 = [NSMutableSet setWithArray:array];
NSLog(@"muSet2 %@",muSet2);
//5.NSDictionary 转化成NSArray
NSArray * allkeys = [dic allKeys];
NSLog(@"allkeys %@",allkeys);
NSArray * allValues = [dic allValues];
NSLog(@"allValues %@",allValues);
//6.字符串转换成数组
NSString * str = @"www.itacast.cn";
NSArray * strArray =[str componentsSeparatedByString:@"."];
NSLog(@"strArray %@",strArray);
第五:NSPointerArray
NSArray的弱引用版本,也可以存储非oc对象,对应着 NSArray,添加元素操作很慢。
1.1,与NSArray的异同
* 相同点:
1.用于有序的插入或移除;
2.遵循 NSFastEnumeration ,可以通过 for...in 来进行遍历。
* 不同点:
1. 可以存储 NULL,并且 NULL 还参与 count 的计算;
2. count 可以 set,如果直接 set count,那么会使用 NULL 占位;
3.可以存储 weak 来修饰成员;
4.成员可以是所有指针类型;
1.2,初始化
NSPointerArray 与 NSMutableArray 很像,都是可变有序集合。最大的不同就是它们的初始化方法,
NSPointerArray
1.初始化方法:
- (instancetype)initWithOptions:(NSPointerFunctionsOptions)options;
- (instancetype)initWithPointerFunctions:(NSPointerFunctions *)functions;
2.类方法:
+ (NSPointerArray *)pointerArrayWithOptions:(NSPointerFunctionsOptions)options;
+ (NSPointerArray *)pointerArrayWithPointerFunctions:(NSPointerFunctions *)functions;
枚举:NSPointerFunctionsOptions
主要分为三大类:
* 内存管理
NSPointerFunctionsStrongMemory :缺省值,在 CG 和 MRC 下强引用成员
NSPointerFunctionsZeroingWeakMemory :已废弃,在 GC 下,弱引用指针,防止悬挂指针
NSPointerFunctionsMallocMemory 与 NSPointerFunctionsMachVirtualMemory : 用于 Mach 的虚拟内存管理
NSPointerFunctionsWeakMemory :在 CG 或者 ARC 下,弱引用成员
* 特性,用于标明对象判等方式
NSPointerFunctionsObjectPersonality : hash 、 isEqual 、对象描述
NSPointerFunctionsOpaquePersonality :pointer 的 hash 、直接判等
NSPointerFunctionsObjectPointerPersonality :pointer 的 hash 、直接判等、对象描述
NSPointerFunctionsCStringPersonality :string 的 hash 、 strcmp 函数、UTF-8 编码方式的描述
NSPointerFunctionsStructPersonality :内存 hash 、 memcmp 函数
NSPointerFunctionsIntegerPersonality :值的 hash
* 内存标识
NSPointerFunctionsCopyIn :根据第二类的选择,来具体处理。
如果是 NSPointerFunctionsObjectPersonality ,则根据 NSCopying 来拷贝。
所以在使用时,可以多个组合,
比如:需要强引用成员、使用对象方式对比、并且 add 时 copy 对象:
NSPointerFunctionsOptions *options = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality | NSPointerFunctionsCopyIn;
NSPointerFunctions
3.添加pointer(NULL也能添加)
- (void)addPointer:(nullable void *)pointer; // add pointer at index 'count'
4.通过索引的方式删除pointer
- (void)removePointerAtIndex:(NSUInteger)index; // everything above index, including holes, slide lower
5.通过索引的方式添加Pointer
- (void)insertPointer:(nullable void *)item atIndex:(NSUInteger)index; // everything at & above index, including holes, slide higher
6.通过索引的方式替换对应Pointer
- (void)replacePointerAtIndex:(NSUInteger)index withPointer:(nullable void *)item; // NULL item is okay; index must be < count
7.剔除集合中为 NULL 的成员
- (void)compact; // eliminate NULLs
注意:
当我们主动给 NSPointerArray 添加 NULL 时,数组会标记有空元素插入,此时 compact 函数才会生效,也就是说, compact 函数会先判断是否有标记,之后才会剔除。
第六:NSMapTable
对应NSDictionary的弱引用版本,添加元素和存取操作都比NSMutableDictionary慢点。
除了 集合的共有特点以外,比起传统字典,它还有一些优势:
key 可以不用遵循 NSCopying 协议;
key 和 value 的内存管理方式可以分开,如:key 是强引用,value 是弱引用;
相比起 NSPointerArray , NSMapTable 的初始化方法要多得多:
1.实例方法,虽然有 capacity 参数,但实际没用到
- (instancetype)initWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions capacity:(NSUInteger)initialCapacity;
- (instancetype)initWithKeyPointerFunctions:(NSPointerFunctions *)keyFunctions valuePointerFunctions:(NSPointerFunctions *)valueFunctions capacity:(NSUInteger)initialCapacity;
2.便利构造器
+ (NSMapTable<KeyType, ObjectType> *)mapTableWithKeyOptions:(NSPointerFunctionsOptions)keyOptions valueOptions:(NSPointerFunctionsOptions)valueOptions;
3.返回指定 key、value 内存管理类型的 map
+ (NSMapTable<KeyType, ObjectType> *)strongToStrongObjectsMapTable NS_AVAILABLE(10_8, 6_0);
+ (NSMapTable<KeyType, ObjectType> *)weakToStrongObjectsMapTable NS_AVAILABLE(10_8, 6_0);
+ (NSMapTable<KeyType, ObjectType> *)strongToWeakObjectsMapTable NS_AVAILABLE(10_8, 6_0);
+ (NSMapTable<KeyType, ObjectType> *)weakToWeakObjectsMapTable NS_AVAILABLE(10_8, 6_0);
其实,这么多的初始化方法就对应着四种搭配:
key 为 strong,value 为 strong
key 为 strong,value 为 weak
key 为 weak,value 为 strong
key 为 weak,value 为 weak
当用 weak 修饰 key 或 value 时,有一方被释放,则该键值对移除。
4. NSMapTable可以使用的函数
FOUNDATION_EXPORT void NSFreeMapTable(NSMapTable *table);
FOUNDATION_EXPORT void NSResetMapTable(NSMapTable *table);
FOUNDATION_EXPORT BOOL NSCompareMapTables(NSMapTable *table1, NSMapTable *table2);
FOUNDATION_EXPORT NSMapTable *NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone);
FOUNDATION_EXPORT BOOL NSMapMember(NSMapTable *table, const void *key, void **originalKey, void **value);
FOUNDATION_EXPORT void *NSMapGet(NSMapTable *table, const void *key);
FOUNDATION_EXPORT void NSMapInsert(NSMapTable *table, const void *key, const void *value);
FOUNDATION_EXPORT void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, const void *value);
FOUNDATION_EXPORT void *NSMapInsertIfAbsent(NSMapTable *table, const void *key, const void *value);
FOUNDATION_EXPORT void NSMapRemove(NSMapTable *table, const void *key);
FOUNDATION_EXPORT NSMapEnumerator NSEnumerateMapTable(NSMapTable *table);
FOUNDATION_EXPORT BOOL NSNextMapEnumeratorPair(NSMapEnumerator *enumerator, void **key, void **value);
FOUNDATION_EXPORT void NSEndMapTableEnumeration(NSMapEnumerator *enumerator);
FOUNDATION_EXPORT NSUInteger NSCountMapTable(NSMapTable *table);
FOUNDATION_EXPORT NSString *NSStringFromMapTable(NSMapTable *table);
FOUNDATION_EXPORT NSArray *NSAllMapTableKeys(NSMapTable *table);
FOUNDATION_EXPORT NSArray *NSAllMapTableValues(NSMapTable *table);
第七:NSHashTable
可以包含弱引用对象的set集合,通常使用weakObjectsHashTable构造函数 ,它的 API 更为简单,与 NSMapTable 同样,初始化方法的 capacity 并未生效。
- (instancetype)initWithOptions:(NSPointerFunctionsOptions)options capacity:(NSUInteger)initialCapacity;
- (instancetype)initWithPointerFunctions:(NSPointerFunctions *)functions capacity:(NSUInteger)initialCapacity;
值得注意的是, NSHashTable 有一个 allObjectes 的属性,返回 NSArray ,即使 NSHashTable 是弱引用成员, allObjects 依然会对成员进行强引用。
typedef struct {NSUInteger _pi; NSUInteger _si; void *_bs;} NSHashEnumerator;
FOUNDATION_EXPORT void NSFreeHashTable(NSHashTable *table);
FOUNDATION_EXPORT void NSResetHashTable(NSHashTable *table);
FOUNDATION_EXPORT BOOL NSCompareHashTables(NSHashTable *table1, NSHashTable *table2);
FOUNDATION_EXPORT NSHashTable *NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone);
FOUNDATION_EXPORT void *NSHashGet(NSHashTable *table, const void *pointer);
FOUNDATION_EXPORT void NSHashInsert(NSHashTable *table, const void *pointer);
FOUNDATION_EXPORT void NSHashInsertKnownAbsent(NSHashTable *table, const void *pointer);
FOUNDATION_EXPORT void *NSHashInsertIfAbsent(NSHashTable *table, const void *pointer);
FOUNDATION_EXPORT void NSHashRemove(NSHashTable *table, const void *pointer);
FOUNDATION_EXPORT NSHashEnumerator NSEnumerateHashTable(NSHashTable *table);
FOUNDATION_EXPORT void *NSNextHashEnumeratorItem(NSHashEnumerator *enumerator);
FOUNDATION_EXPORT void NSEndHashTableEnumeration(NSHashEnumerator *enumerator);
FOUNDATION_EXPORT NSUInteger NSCountHashTable(NSHashTable *table);
FOUNDATION_EXPORT NSString *NSStringFromHashTable(NSHashTable *table);
FOUNDATION_EXPORT NSArray *NSAllHashTableObjects(NSHashTable *table);
第八:小结
这NSPointerArray,NSMapTable,NSHashTable类集合类型在 10.5 之后引入,比传统的集合类型更为强大,但是它们的方法却没有传统集合类型多,比如对于 NSPointerArray 来说:
* 操作均基于 index,无法通过 object 来进行操作;
* 无法直接插入 array,或用 array 初始化;
* 查找功能没有 NSArray 强大;
* 没有逆序、排序等 API 提供
以上几点仅仅是举的例子,所以 NSPointerArray 也并没有看起来的那么强大,一切选择标准,都应该依据具体需求。