OC集合类是一些非常有用的工具类,它可以用于存储多个数量不等的对象,并可以实现常用的数据结构(栈、队列等),此外,OC集合还可用于保存具有映射关系的关联数组。OC的集合大致可以分为:NSArray、NSSet、NSDictionary三种体系。NSArray代表有序可重复的集合;NSSet代表无序不可重复的集合;NSDictionary代表具有映射关系的集合。显然,这三类集合分别对应这Java中的List、Set和Map。
集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的指针变量),而集合里则只能保存对象(实际上保存的是对象的指针变量,但通常认为集合里爆粗你的是对象)。
1、NSArray代表元素有序、可重复的一个集合,集合中每个元素都有其对应的顺序索引。NSArray集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。NSArray分别提供了类方法和实例方法来创建NSArray,两种创建方式基本类似,只是类方法以array开头,实例方法以init开头。集中常见的NSArray创建对象的方法如下:
参考NSArray类的文档,可以看到NSArray集合的方法大致包含如下几类:
1 #import <Foundation/Foundation.h>
2
3 int main(int argc , char * argv[])
4 {
5 @autoreleasepool{
6 //创建一个NSArray对象,直接传入多个元素,其中最后一个nil表示NSArray元素结束,其实这个nil并不会存入NSArray中
7 NSArray* array = [NSArray arrayWithObjects:
8 @"疯狂iOS讲义", @"疯狂Android讲义"
9 , @"疯狂Ajax讲义", @"疯狂XML讲义"
10 , @"Struts 2.x权威指南" , nil];
11 NSLog(@"第一个元素:%@" , [array objectAtIndex:0]);
12 NSLog(@"索引为1的元素:%@" , [array objectAtIndex:1]);
13 NSLog(@"最后一个元素:%@" , [array lastObject]);
14 // 获取索引从2~5的元素组成的新集合,NSIndexSet类与NSSet基本类似,区别只是NSIndexSet 集合主要用于保存所引致,因此,其集合元素都是NSUInteger对象
15 NSArray* arr1 = [array objectsAtIndexes: [NSIndexSet
16 indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
17 NSLog(@"%@" , arr1);
18 // 获取元素在集合中的位置
19 NSLog(@"疯狂Android讲义的位置为:%ld" ,
20 [array indexOfObject:@"疯狂Android讲义"]);
21 // 获取元素在集合的指定范围中的位置
22 NSLog(@"在2~5范围疯狂Android讲义的位置为:%ld" ,
23 [array indexOfObject:@"疯狂Android讲义"
24 inRange:NSMakeRange(2, 3)]); // ①
25 // 向数组的最后追加一个元素。
26 // 原NSArray本身并没有改变,只是将新返回的NSArray赋给array
27 array = [array arrayByAddingObject:@"孙悟空"];
28 // 向array数组的最后追加另一个数组的所有元素。
29 // 原NSArray本身并没有改变,只是将新返回的NSArray赋给array
30 array = [array arrayByAddingObjectsFromArray:
31 [NSArray arrayWithObjects:@"宝玉" , @"黛玉" , nil]];
32 for (int i = 0 ; i < array.count; i++)
33 {
34 // NSLog(@"%@" , [array objectAtIndex:i]);
35 // 上面代码也可简写为如下代码
36 NSLog(@"%@" , array[i]);
37
38 }
39 // 获取array数组中索引为5~8处的所有元素
40 NSArray* arr2 = [array subarrayWithRange: NSMakeRange(5, 3)];
41 // 将NSArray集合的元素写入文件
42 [arr2 writeToFile:@"myFile.txt" atomically:YES];
43 }
44 }
2、NSArray允许对集合中所有的元素或部分元素整体调用方法,如果只是简单地调用集合元素的方法,则可通过NSArray的如下两种方式来实现:
如果希望对集合中所有元素进行隐式遍历,并使用集合元素来执行某一段代码,则可通过一下的方法来完成:
1 import <Foundation/Foundation.h>
2 #import "FKUser.h"
3
4 int main(int argc , char * argv[])
5 {
6 @autoreleasepool{
7 // 初始化NSArray对象
8 NSArray* array = [NSArray arrayWithObjects:
9 [[FKUser alloc] initWithName:@"sun" pass:@"123"],
10 [[FKUser alloc] initWithName:@"bai" pass:@"345"],
11 [[FKUser alloc] initWithName:@"zhu" pass:@"654"],
12 [[FKUser alloc] initWithName:@"tang" pass:@"178"],
13 [[FKUser alloc] initWithName:@"niu" pass:@"155"],
14 nil];
15 // 对集合元素整体调用方法
16 [array makeObjectsPerformSelector:@selector(say:)
17 withObject:@"下午好,NSArray真强大!"];
18 NSString* content = @"疯狂iOS讲义";
19 // 迭代集合内指定范围内元素,并使用该元素来执行代码块
20 [array enumerateObjectsAtIndexes:
21 [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2,2)]
22 options:NSEnumerationReverse
23 // 代码块的第一个参数代表正在遍历的集合元素
24 // 代码块的第二个参数代表正在遍历的集合元素的索引
25 usingBlock: ^(id obj, NSUInteger idx, BOOL *stop)
26 {
27 NSLog(@"正在处理第%ld个元素:%@" , idx , obj);
28 [obj say:content];
29 }];
30 }
31 }
对NSArray进行排序:
1 #import <Foundation/Foundation.h>
2
3 // 定义比较函数,根据两个对象的intValue进行比较
4 NSInteger intSort(id num1, id num2, void *context)
5 {
6 int v1 = [num1 intValue];
7 int v2 = [num2 intValue];
8 if (v1 < v2)
9 return NSOrderedAscending;
10 else if (v1 > v2)
11 return NSOrderedDescending;
12 else
13 return NSOrderedSame;
14 }
15 int main(int argc , char * argv[])
16 {
17 @autoreleasepool{
18 // 初始化一个元素为NSString的NSArray对象
19 NSArray* array1 = [NSArray arrayWithObjects:
20 @"Objective-C" , @"C" , @"C++"
21 , @"Ruby" , @"Perl" , @"Python" , nil];
22 // 使用集合元素的compare:方法执行排序
23 array1 = [array1 sortedArrayUsingSelector:
24 @selector(compare:)];
25 NSLog(@"%@" , array1);
26 // 初始化一个元素为NSNumber的NSArray对象
27 NSArray* array2 = [NSArray arrayWithObjects:
28 [NSNumber numberWithInt:20],
29 [NSNumber numberWithInt:12],
30 [NSNumber numberWithInt:-8],
31 [NSNumber numberWithInt:50],
32 [NSNumber numberWithInt:19], nil];
33 // 使用intSort函数执行排序
34 array2 = [array2 sortedArrayUsingFunction:intSort
35 context:nil];
36 NSLog(@"%@" , array2);
37 // 使用代码块对集合元素进行排序
38 NSArray* array3 = [array2 sortedArrayUsingComparator:
39 ^(id obj1, id obj2)
40 {
41 // 该代码块就是根据集合元素的 intValue进行比较
42 if ([obj1 intValue] > [obj2 intValue])
43 {
44 return NSOrderedDescending;
45 }
46 if ([obj1 intValue] < [obj2 intValue])
47 {
48 return NSOrderedAscending;
49 }
50 return NSOrderedSame;
51 }];
52 NSLog(@"%@" , array3);
53 }
54 }
对NSArray进行遍历:
上面两个方法都返回一个NSEnumerator枚举器,该枚举器只包含两个方法:
1 #import <Foundation/Foundation.h>
2
3 int main(int argc , char * argv[])
4 {
5 @autoreleasepool{
6 // 读取前面写入磁盘的文件,用文件内容来初始化NSArray集合
7 NSArray* array = [NSArray arrayWithContentsOfFile:
8 @"myFile.txt"];
9 // 获取NSArray的顺序枚举器
10 NSEnumerator* en = [array objectEnumerator];
11 id object;
12 while(object = [en nextObject])
13 {
14 NSLog(@"%@" , object);
15 }
16 NSLog(@"------下面逆序遍历------");
17 // 获取NSArray的逆序枚举器
18 en = [array reverseObjectEnumerator];
19 while(object = [en nextObject])
20 {
21 NSLog(@"%@" , object);
22 }
23 }
24 }
1 #import <Foundation/Foundation.h>
2
3 int main(int argc , char * argv[])
4 {
5 @autoreleasepool{
6 // 读取前面写入磁盘的文件,用文件内容来初始化NSArray集合
7 NSArray* array = [NSArray arrayWithContentsOfFile:
8 @"myFile.txt"];
9 for(id object in array)
10 {
11 NSLog(@"%@" , object);
12 }
13 }
14 }
3、NSArray代表集合不可变元素,一旦NSArray创建成功,程序就不能向集合中添加新的元素,不能删除集合中已有的元素,也不能替换集合元素。NSArray有一个子类NSMutableArray,NSMutableArray代表集合元素可变的集合,因此,程序可以向集合中添加新元素,可以删除集合中已有的元素。
由于NSMutableArray是NSArray的子类,所以继承了NSArray中的所有方法,此外还提供了一系列可以对数组进行修改的方法:
1 #import <Foundation/Foundation.h>
2
3 // 定义一个函数,该函数用于把NSArray集合转换为字符串
4 NSString* NSCollectionToString(NSArray* array)
5 {
6 NSMutableString* result = [NSMutableString
7 stringWithString:@"["];
8 for(id obj in array)
9 {
10 [result appendString:[obj description]];
11 [result appendString:@", "];
12 }
13 // 获取字符串长度
14 NSUInteger len = [result length];
15 // 去掉字符串最后的两个字符
16 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
17 [result appendString:@"]"];
18 return result;
19 }
20 int main(int argc , char * argv[])
21 {
22 @autoreleasepool{
23 // 读取前面写入磁盘的文件,用文件内容来初始化NSMutableArray集合
24 NSMutableArray* array = [NSMutableArray
25 arrayWithContentsOfFile:@"myFile.txt"];
26 // 向集合最后添加一个元素
27 [array addObject:@"疯狂iOS讲义"];
28 NSLog(@"最后追加一个元素后:%@" , NSCollectionToString(array));
29 // 使用NSArray向集合尾部添加多个元素
30 [array addObjectsFromArray: [NSArray
31 arrayWithObjects:@"张飞" , @"关羽",nil]];
32 NSLog(@"最后追加两个元素后:%@" , NSCollectionToString(array));
33 // 向集合的指定位置插入一个元素
34 [array insertObject:@"疯狂Ajax讲义" atIndex:2];
35 NSLog(@"在索引为2处插入一个元素后:%@"
36 , NSCollectionToString(array));
37 // 使用NSArray向集合指定位置插入多个元素
38 [array insertObjects: [NSArray
39 arrayWithObjects:@"武松" , @"林冲",nil]
40 atIndexes:[NSIndexSet indexSetWithIndexesInRange
41 :NSMakeRange(3,2)]];
42 NSLog(@"插入多个元素后:%@" , NSCollectionToString(array));
43 // 删除集合最后一个元素
44 [array removeLastObject];
45 NSLog(@"删除最后一个元素后:%@" , NSCollectionToString(array));
46 // 删除集合中指定索引处的元素
47 [array removeObjectAtIndex:5];
48 NSLog(@"删除索引为5处的元素后:%@" , NSCollectionToString(array));
49 // 删除2~5处元素
50 [array removeObjectsInRange:NSMakeRange(2, 3)];
51 NSLog(@"删除索引为2~5处的元素后:%@"
52 , NSCollectionToString(array));
53 // 替换索引为2处的元素
54 [array replaceObjectAtIndex:2 withObject:@"疯狂Android讲义"];
55 NSLog(@"替换索引为2处的元素后:%@"
56 , NSCollectionToString(array));
57 }
58 }
4、NSArray是一个容纳多个对象的集合,NSArray允许直接对集合中的所有元素进行整体的KVC编码,NSArray提供了如下两个方法:
此外,NSArray还为集合中所有元素或部分元素进行KVO编程提供了如下方法,但是根据Apple官方文档,NSArray本身不能被监听,所以调用此方法会引发异常。
1 #import <Foundation/Foundation.h>
2 #import "FKUser.h"
3 // 定义一个函数,该函数用于把NSArray集合转换为字符串
4 NSString* NSCollectionToString(NSArray* array)
5 {
6 NSMutableString* result = [NSMutableString
7 stringWithString:@"["];
8 for(id obj in array)
9 {
10 [result appendString:[obj description]];
11 [result appendString:@", "];
12 }
13 // 获取字符串长度
14 NSUInteger len = [result length];
15 // 去掉字符串最后的两个字符
16 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
17 [result appendString:@"]"];
18 return result;
19 }
20 int main(int argc , char * argv[])
21 {
22 @autoreleasepool{
23 // 初始化NSArray对象
24 NSArray* array = [NSArray arrayWithObjects:
25 [[FKUser alloc] initWithName:@"sun" pass:@"123"],
26 [[FKUser alloc] initWithName:@"bai" pass:@"345"],
27 [[FKUser alloc] initWithName:@"zhu" pass:@"654"],
28 [[FKUser alloc] initWithName:@"tang" pass:@"178"],
29 [[FKUser alloc] initWithName:@"niu" pass:@"155"],
30 nil];
31 // 获取所有集合元素的name属性组成的新集合
32 id newArr = [array valueForKey:@"name"];
33 NSLog(@"%@" , NSCollectionToString(newArr));
34 // 对集合中所有元素整体进行KVC编程
35 // 将所有集合元素的name属性改为"新名字"
36 [array setValue:@"新名字" forKey:@"name"];
37 NSLog(@"%@" , NSCollectionToString(array));
38 }
39 }
NSSet和NSMutableSet的区别与NSArray和NSMutableArray之间的区别是一样的。NSSet表示元素个数和内容均不可变的集合,NSMutableSet则表示元素个数和内容可变的集合。
1、NSSet是一个广泛使用的集合,NSSet按Hash算法来储存集合中的元素,因此具有很好的存取和查找性能。也正因为是才用Hash算法储存元素,NSSet不能保证元素的添加顺序,顺序可能会发生变化。因此,与NSArray相比,NSSet的最大的区别就说元素没有索引,不能根据根据索引来操作元素。
NSSet与NSArray的相同点:
1 #import <Foundation/Foundation.h>
2
3 // 定义一个函数,该函数可把NSArray或NSSet集合转换为字符串
4 NSString* NSCollectionToString(id collection)
5 {
6 NSMutableString* result = [NSMutableString
7 stringWithString:@"["];
8 // 使用快速枚举遍历NSSet集合
9 for(id obj in collection)
10 {
11 [result appendString:[obj description]];
12 [result appendString:@", "];
13 }
14 // 获取字符串长度
15 NSUInteger len = [result length];
16 // 去掉字符串最后的两个字符
17 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
18 [result appendString:@"]"];
19 return result;
20 }
21 int main(int argc , char * argv[])
22 {
23 @autoreleasepool{
24 // 用4个元素初始化NSSet集合,
25 // 故意传入两个相等的元素, NSSet集合只会保留一个元素
26 NSSet* set1 = [NSSet setWithObjects:
27 @"疯狂iOS讲义" , @"疯狂Android讲义",
28 @"疯狂Ajax讲义" ,@"疯狂iOS讲义" , nil];
29 // 程序输出set1集合中元素个数为3
30 NSLog(@"set1集合中元素个数为%ld" , [set1 count]);
31 NSLog(@"s1集合:%@" , NSCollectionToString(set1));
32 NSSet* set2 = [NSSet setWithObjects:
33 @"孙悟空" , @"疯狂Android讲义",
34 @"猪八戒" , nil];
35 NSLog(@"s2集合:%@" , NSCollectionToString(set2));
36 // 向set1集合中添加单个元素,将添加元素后生成的新集合赋给set1
37 set1 = [set1 setByAddingObject:@"Struts 2.1权威指南"];
38 NSLog(@"添加一个元素后:%@" , NSCollectionToString(set1));
39 // 使用NSSet集合向set1集合中添加多个元素,相当计算两个集合的并集
40 NSSet* s = [set1 setByAddingObjectsFromSet:set2];
41 NSLog(@"set1与set2的并集:%@" , NSCollectionToString(s));
42 // 计算两个NSSet集合的是否有交集
43 BOOL b = [set1 intersectsSet:set2];
44 NSLog(@"set1与set2是否有交集:%d" , b);// 将输出代表YES的1
45 // 判断set2是否是set1的子集
46 BOOL bo = [set2 isSubsetOfSet:set1];
47 NSLog(@"set2是否为set1的子集:%d" , bo);// 将输出代表NO的0
48 // 判断NSSet集合是否包含指定元素
49 BOOL bb = [set1 containsObject:@"疯狂Ajax讲义"];
50 NSLog(@"set1是否包含\"疯狂Ajax讲义\":%d" , bb);// 将输出代表YES的1
51 // 下面两行代码将取出相同的元素,但取出哪个元素是不确定的。
52 NSLog(@"set1取出一个元素:%@"
53 , [set1 anyObject]);
54 NSLog(@"set1取出一个元素:%@"
55 , [set1 anyObject]);
56 // 使用代码块对集合元素进行过滤
57 NSSet* filteredSet = [set1 objectsPassingTest:
58 ^(id obj, BOOL *stop)
59 {
60 return (BOOL)([obj length] > 8);
61 }];
62 NSLog(@"set1中元素的长度大于8的集合元素有:%@"
63 , NSCollectionToString(filteredSet));
64 }
65 }
2、前面已经说过了,NSSet集合中的元素是不能重复的,因此每次再加入一个新元素时,需要判断新元素是否与集合中已有元素重复。判断标准是这样:
1 #import <Foundation/Foundation.h>
2 #import "FKUser.h"
3
4 // 定义一个函数,该函数可把NSArray或NSSet集合转换为字符串
5 NSString* NSCollectionToString(id array)
6 {
7 NSMutableString* result = [NSMutableString
8 stringWithString:@"["];
9 for(id obj in array)
10 {
11 [result appendString:[obj description]];
12 [result appendString:@", "];
13 }
14 // 获取字符串长度
15 NSUInteger len = [result length];
16 // 去掉字符串最后的两个字符
17 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
18 [result appendString:@"]"];
19 return result;
20 }
21 int main(int argc , char * argv[])
22 {
23 @autoreleasepool{
24 NSSet* set = [NSSet setWithObjects:
25 [[FKUser alloc] initWithName:@"sun" pass:@"123"],
26 [[FKUser alloc] initWithName:@"bai" pass:@"345"],
27 [[FKUser alloc] initWithName:@"sun" pass:@"123"],
28 [[FKUser alloc] initWithName:@"tang" pass:@"178"],
29 [[FKUser alloc] initWithName:@"niu" pass:@"155"],
30 nil];
31 NSLog(@"set集合元素的个数:%ld" , [set count]);
32 NSLog(@"%@" , NSCollectionToString(set));
33 }
34 }
所以如果需要某个类的对象保存到NSSet中,重写这个类的isEqual:方法和hash方法时,应该尽量保证两个对象通过isEqual:方法比较返回YES时,他们的hash方法返回值也是一样的。
3、NSMutableSet继承自NSSet,它代表一个集合元素可变的NSSet集合。由于NSMutableSet可以动态地添加集合元素,因此,创建NSMutableSet集合时可以指定底层hash表的初始容量。NSMutableSet在NSSet上增加了增加元素、删除元素的方法之外,还增加了对集合进行计算交集、并集和差集的方法。
1 #import <Foundation/Foundation.h>
2
3
4 // 定义一个函数,该函数可把NSArray或NSSet集合转换为字符串
5 NSString* NSCollectionToString(id collection)
6 {
7 NSMutableString* result = [NSMutableString
8 stringWithString:@"["];
9 // 使用快速枚举遍历NSSet集合
10 for(id obj in collection)
11 {
12 [result appendString:[obj description]];
13 [result appendString:@", "];
14 }
15 // 获取字符串长度
16 NSUInteger len = [result length];
17 // 去掉字符串最后的两个字符
18 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
19 [result appendString:@"]"];
20 return result;
21 }
22 int main(int argc , char * argv[])
23 {
24 @autoreleasepool{
25 // 创建一个初始容量为10的Set集合
26 NSMutableSet* set = [NSMutableSet setWithCapacity:10];
27 [set addObject:@"疯狂iOS讲义"];
28 NSLog(@"添加1个元素后:%@" , NSCollectionToString(set));
29 [set addObjectsFromArray: [NSArray
30 arrayWithObjects:@"疯狂Android讲义"
31 , @"疯狂Ajax讲义" , @"疯狂XML讲义" ,nil]];
32 NSLog(@"使用NSArray添加3个元素后:%@" , NSCollectionToString(set));
33 [set removeObject:@"疯狂XML讲义"];
34 NSLog(@"删除1个元素后:%@" , NSCollectionToString(set));
35 // 再次创建一个Set集合
36 NSSet* set2 = [NSSet setWithObjects:
37 @"孙悟空", @"疯狂iOS讲义" , nil];
38 // 计算两个集合的并集,直接改变set集合的元素
39 [set unionSet: set2];
40 // 计算两个集合的差集,直接改变set集合的元素
41 // [set minusSet: set2];
42 // 计算两个集合的交集,直接改变set集合的元素
43 // [set intersectSet: set2];
44 // 用set2的集合元素替换set的集合元素,直接改变set集合的元素
45 // [set setSet: set2];
46 NSLog(@"%@" , NSCollectionToString(set));
47 }
48 }
4、NSCountedSet是NSMutableSet的子类,与普通NSMutableSet集合不同的是,NSCountedSet为每个元素额外维护了一个添加次数的状态。当程序向NSCountedSet中添加一个元素时,如果NSCountedSet集合中不包含该元素,那么NSCountedSet真正接纳该元素,并将该元素的添加次数标注为1 ;当程序向NSCountedSet中添加一个元素时,如果NSCountedSet集合中已经包含该元素,那么NSCountedSet不会接纳该元素,但会将该元素的添加次数增加1 。
当程序从NSCountedSet中删除一个元素时,NSCountedSet只是将该元素对应的添加次数减1,只有当该元素的添加次数为0时,该元素才会真正从NSCountedSet集合中删除。
1 #import <Foundation/Foundation.h>
2
3 // 定义一个函数,该函数可把NSArray或NSSet集合转换为字符串
4 NSString* NSCollectionToString(id collection)
5 {
6 NSMutableString* result = [NSMutableString
7 stringWithString:@"["];
8 // 使用快速枚举遍历NSSet集合
9 for(id obj in collection)
10 {
11 [result appendString:[obj description]];
12 [result appendString:@", "];
13 }
14 // 获取字符串长度
15 NSUInteger len = [result length];
16 // 去掉字符串最后的两个字符
17 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
18 [result appendString:@"]"];
19 return result;
20 }
21 int main(int argc , char * argv[])
22 {
23 @autoreleasepool{
24 NSCountedSet* set = [NSCountedSet setWithObjects:
25 @"疯狂iOS讲义" , @"疯狂Android讲义",
26 @"疯狂Ajax讲义" , nil];
27 [set addObject:@"疯狂iOS讲义"];
28 [set addObject:@"疯狂iOS讲义"];
29 // 输出集合元素
30 NSLog(@"%@" , NSCollectionToString(set));
31 // 获取指定元素的添加顺序
32 NSLog(@"\"疯狂iOS讲义\"的添加次数为:%ld"
33 , [set countForObject:@"疯狂iOS讲义"]);
34 // 删除元素
35 [set removeObject:@"疯狂iOS讲义"];
36 NSLog(@"删除\"疯狂iOS讲义\"1次后的结果:%@"
37 , NSCollectionToString(set));
38 NSLog(@"删除\"疯狂iOS讲义\"1次后的添加次数为:%ld"
39 , [set countForObject:@"疯狂iOS讲义"]);
40 // 重复删除元素
41 [set removeObject:@"疯狂iOS讲义"];
42 [set removeObject:@"疯狂iOS讲义"];
43 NSLog(@"删除\"疯狂iOS讲义\"3次后的结果:%@"
44 , NSCollectionToString(set));
45 }
46 }
5、有序集合NSOrderedSet和NSMutableOrderedSet是两个非常nag奇怪的集合,他们既具有NSSet集合的特征,又具有NSArray类似的功能。(类似于Java中的LinkedHashSet集合,而NSSet就类似Java中的HashSet)
1 #import <Foundation/Foundation.h>
2
3 // 定义一个函数,该函数可把NSArray或NSSet集合转换为字符串
4 NSString* NSCollectionToString(id collection)
5 {
6 NSMutableString* result = [NSMutableString
7 stringWithString:@"["];
8 // 使用快速枚举遍历NSSet集合
9 for(id obj in collection)
10 {
11 [result appendString:[obj description]];
12 [result appendString:@", "];
13 }
14 // 获取字符串长度
15 NSUInteger len = [result length];
16 // 去掉字符串最后的两个字符
17 [result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
18 [result appendString:@"]"];
19 return result;
20 }
21 int main(int argc , char * argv[])
22 {
23 @autoreleasepool{
24 // 创建NSOrderedSet集合,故意使用重复的元素
25 // 程序看到程序只会保留一个元素
26 NSOrderedSet* set = [NSOrderedSet orderedSetWithObjects:
27 [NSNumber numberWithInt:40],
28 [NSNumber numberWithInt:12],
29 [NSNumber numberWithInt:-9],
30 [NSNumber numberWithInt:28],
31 [NSNumber numberWithInt:12],
32 [NSNumber numberWithInt:17],
33 nil];
34 NSLog(@"%@" , NSCollectionToString(set));
35 // 下面方法都是根据索引来操作集合元素
36 // 获取第一个元素
37 NSLog(@"set集合的第一个元素 :%@" , [set firstObject]);
38 // 获取最后一个元素
39 NSLog(@"set集合的第一个元素 :%@" , [set lastObject]);
40 // 获取指定索引处的元素
41 NSLog(@"set集合中索引为2的元素 :%@" , [set objectAtIndex:2]);
42 NSLog(@"28在set集合中的索引为:%ld" , [set indexOfObject:
43 [NSNumber numberWithInt:28]]);
44 // 对集合进行过滤,获取元素值大于20的集合元素的索引
45 NSIndexSet* indexSet = [set indexesOfObjectsPassingTest:
46 ^(id obj, NSUInteger idx, BOOL *stop)
47 {
48 return (BOOL)([obj intValue] > 20);
49 }];
50 NSLog(@"set集合中元素值大于20的元素的索引为:%@" , indexSet);
51 }
52 }
NSMutableOrderedSet是NSOrderedSet的子类,代表集合元素可变的有序集合。NSMutableOrderedSet在NSOrderedSet的基础上增加了添加元素、删除元素、替换元素、集合排序,以及计算集合的交、并、差等功能。
1、NSDictoinary用于保存具有映射关系的数据,因此NSDictoinary集合中保存这两组值,一组用于保存NSDictoinary中的key,另一组用于保存NSDictoinary中的value。注意,key和value都可以是任意指针类型的数据,NSDictoinary中的key不允许重复。key和value之间存在单向一对一关系,即通过指定的key总能找到唯一的确定的value。从NSDictoinary中取出数据时,只要给定指定的key,就可以取出对应的value。
如果将NSDictoinary中的key和value分开来看,NSDictoinary所有的key放在一起,他们就组成了一个NSSet集合,所有的key没有顺序,key与key不能重复。实际上,NSDictoinary中包含了一个allKeys方法,只是该方法的返回值是NSArray类型,其实是该方法内部已经将NSSet集合进一步转化为NSArray了。
NSDictoinary的常用方法就不在这里进行列举了,需要的可以自行查看相关的参考文档 NSDictionary文档
NSDictionary、NSMutableDictionary的基本用法
1 #import <Foundation/Foundation.h>
2 #import "NSDictionary+print.h"
3 #import "FKUser.h"
4
5 int main(int argc , char * argv[])
6 {
7 @autoreleasepool{
8 // 直接使用多个value,key的形式创建NSDictionary对象
9 NSDictionary* dict = [NSDictionary
10 dictionaryWithObjectsAndKeys:
11 [[FKUser alloc] initWithName:@"sun"
12 pass:@"123"], @"one",
13 [[FKUser alloc] initWithName:@"bai"
14 pass:@"345"], @"two",
15 [[FKUser alloc] initWithName:@"sun"
16 pass:@"123"], @"three",
17 [[FKUser alloc] initWithName:@"tang"
18 pass:@"178"], @"four",
19 [[FKUser alloc] initWithName:@"niu"
20 pass:@"155"], @"five" , nil];
21 [dict print];
22 NSLog(@"dict包含%ld个key-value对", [dict count]);
23 NSLog(@"dict的所有key为:%@" , [dict allKeys]);
24 NSLog(@"<FKUser[name=sun,pass=123]>对应的所有key为:%@"
25 , [dict allKeysForObject:
26 [[FKUser alloc] initWithName:@"sun"
27 pass:@"123"]]);
28 // 获取遍历dict所有value的枚举器
29 NSEnumerator* en = [dict objectEnumerator];
30 NSObject* value;
31 // 使用枚举器来遍历dict中所有value。
32 while(value = [en nextObject])
33 {
34 NSLog(@"%@" , value);
35 }
36 // 使用指定代码块来迭代执行该集合中所有key-value对。
37 [dict enumerateKeysAndObjectsUsingBlock:
38 // 该集合包含多个key-value对,下面代码块就执行多少次
39 ^(id key, id value, BOOL *stop)
40 {
41 NSLog(@"key的值为:%@" , key);
42 [value say:@"疯狂iOS讲义"];
43 }];
44 }
45 }
对NSDictoinary的所有key进行排序,与NSArray的三种排序方法类似:
1 #import <Foundation/Foundation.h>
2 #import "NSDictionary+print.h"
3
4 int main(int argc , char * argv[])
5 {
6 @autoreleasepool{
7 // 直接使用多个value,key的形式创建NSDictionary对象
8 NSDictionary* dict = [NSDictionary
9 dictionaryWithObjectsAndKeys:
10 @"Objective-C" , @"one",
11 @"Ruby" , @"two",
12 @"Python" , @"three",
13 @"Perl" , @"four", nil];
14 // 打印dict集合的所有元素
15 [dict print];
16 // 获取所有直接调用value的compare:方法对所有key进行排序。
17 // 返回排好序的所有key组成的NSArray。
18 NSArray* keyArr1 = [dict keysSortedByValueUsingSelector:
19 @selector(compare:)];
20 NSLog(@"%@" , keyArr1);
21 NSArray* keyArr2 = [dict keysSortedByValueUsingComparator:
22 // 对NSDictionary的value进行比较,字符串越长,即可认为该value越大
23 ^(id value1, id value2)
24 {
25 // 下面定义比较大小的标准:字符串越长,即可认为value越大
26 if([value1 length] > [value2 length])
27 {
28 return NSOrderedDescending;
29 }
30 if([value1 length] < [value2 length])
31 {
32 return NSOrderedAscending;
33 }
34 return NSOrderedSame;
35 }];
36 NSLog(@"%@" , keyArr2);
37 // 将NSDictionary的内容输出到指定文件中
38 [dict writeToFile:@"mydict.txt" atomically:YES];
39 }
40 }
NSDictionary还提供了方法可以对NSDictionary的所有的key执行过滤,这些方法执行完后将返回满足过滤条件的key组成NSSet。
1 #import <Foundation/Foundation.h>
2 #import "NSDictionary+print.h"
3
4 int main(int argc , char * argv[])
5 {
6 @autoreleasepool{
7 // 直接使用多个value,key的形式创建NSDictionary对象
8 NSDictionary* dict = [NSDictionary
9 dictionaryWithObjectsAndKeys:
10 [NSNumber numberWithInt:89] , @"Objective-C",
11 [NSNumber numberWithInt:69] , @"Ruby",
12 [NSNumber numberWithInt:75] , @"Python",
13 [NSNumber numberWithInt:109] , @"Perl", nil];
14 // 打印dict集合的所有元素
15 [dict print];
16 // 对NSDictionary的所有key进行过滤
17 NSSet* keySet = [dict keysOfEntriesPassingTest:
18 // 对NSDictionary的value进行比较,字符串越长,即可认为该value越大
19 ^(id key, id value, BOOL* stop)
20 {
21 // 当value的值大于80时返回YES
22 // 这意味着只有value的值大于80的key才会被保存下来
23 return (BOOL)([value intValue] > 80);
24 }];
25 NSLog(@"%@" , keySet);
26 }
27 }
如果使用自定义的类作为NSDictionary的key,则该自定义类需要满足如下条件:
1 #import "FKUser.h"
2
3 @implementation FKUser
4 @synthesize name;
5 @synthesize pass;
6 - (id) initWithName:(NSString*) aName
7 pass:(NSString*) aPass
8 {
9 if(self = [super init])
10 {
11 name = aName;
12 pass = aPass;
13 }
14 return self;
15 }
16 - (void) say:(NSString*) content
17 {
18 NSLog(@"%@说:%@",self.name , content);
19 }
20 // 会重写isEqual:方法,重写该方法的比较标准是,
21 // 如果两个FKUser的name、pass相等,即可认为两个FKUser相等。
22 - (BOOL) isEqual:(id)other
23 {
24 if(self == other)
25 {
26 return YES;
27 }
28 if([other class] == FKUser.class)
29 {
30 FKUser* target = (FKUser*)other;
31 return [self.name isEqualToString:target.name]
32 && [self.pass isEqualToString:target.pass];
33 }
34 return NO;
35 }
36 // 会重写isEqual:方法,重写该方法的比较标准是,
37 // 如果两个FKUser的name、pass相等,即可认为两个FKUser相等。
38 - (NSUInteger) hash
39 {
40 NSUInteger nameHash = name == nil ? 0 : [name hash];
41 NSUInteger passHash = pass == nil ? 0 : [pass hash];
42 return nameHash * 31 + passHash;
43
44
45 }
46 // 重写description方法,可以直接看到FKUser对象的状态
47 - (NSString*) description
48 {
49 return [NSString stringWithFormat:
50 @"<FKUser[name=%@, pass=%@]>"
51 , self.name , self.pass];
52 }
53 - (id)copyWithZone:(NSZone *)zone
54 {
55 NSLog(@"--正在复制--");
56 // 复制一个对象
57 FKUser* newUser = [[[self class] allocWithZone:zone] init];
58 // 将被复制对象的实变量的值赋给新对象的实例变量
59 newUser->name = name;
60 newUser->pass = pass;
61 return newUser;
62 }
63 @end
1 #import <Foundation/Foundation.h>
2 #import "NSDictionary+print.h"
3 #import "FKUser.h"
4
5 int main(int argc , char * argv[])
6 {
7 @autoreleasepool{
8 FKUser* u1 = [[FKUser alloc] initWithName:@"bai"
9 pass:@"345"];
10 // 直接使用多个value,key的形式创建NSDictionary对象
11 NSDictionary* dict = [NSDictionary
12 dictionaryWithObjectsAndKeys:
13 @"one", [[FKUser alloc] initWithName:@"sun"
14 pass:@"123"],
15 @"two", u1,
16 @"three",[[FKUser alloc] initWithName:@"sun"
17 pass:@"123"],
18 @"four",[[FKUser alloc] initWithName:@"tang"
19 pass:@"178"],
20 @"five" ,[[FKUser alloc] initWithName:@"niu"
21 pass:@"155"], nil];
22 // 将u1的密码设为nil
23 u1.pass = nil;
24 // 由于NSDictionary并未直接使用u1所指向的FKUser作为key,
25 // 而是先复制了u1所指向对象的副本,然后以该副本作为key。
26 // 因此程序将可以看到dict的key不会受到任何影响。
27 [dict print];
28 }
29 }
2、NSMutableDictionary是NSDictionary的子类,它代表一个key-value可变的NSDictionary字典集合。同样由于NSMutableDictionary可以动态地添加key-value对,因此,创建NSMutableDictionary集合时可以指定初始容量。类似NSMutableArray与NSArray的关系,NSMutableDictionary主要在NSDictionary的基础上增加了添加、删除key-value对的方法。具体参见 NSMutableDictionary文档
1 #import <Foundation/Foundation.h>
2 #import "NSDictionary+print.h"
3
4 int main(int argc , char * argv[])
5 {
6 @autoreleasepool{
7 // 直接使用多个value,key的形式创建NSDictionary对象
8 NSMutableDictionary* dict = [NSMutableDictionary
9 dictionaryWithObjectsAndKeys:
10 [NSNumber numberWithInt:89] , @"疯狂Android讲义", nil];
11 // 使用下标法设置key-value对。
12 // 由于NSDictionary中已存在该key,
13 // 因此此处设置的value会覆盖前面的value。
14 dict[@"疯狂Android讲义"] = [NSNumber numberWithInt:99];
15 [dict print];
16 NSLog(@"--再次添加key-value对--");
17 dict[@"疯狂XML讲义"] = [NSNumber numberWithInt:69];
18 [dict print];
19 NSDictionary* dict2 = [NSDictionary
20 dictionaryWithObjectsAndKeys:
21 [NSNumber numberWithInt:79] , @"疯狂Ajax讲义",
22 [NSNumber numberWithInt:89] , @"Struts 2.x权威指南"
23 , nil];
24 // 将另外一个NSDictionary中的key-value对添加到当前NSDictionary中
25 [dict addEntriesFromDictionary:dict2];
26 [dict print];
27 // 根据key来删除key-value对
28 [dict removeObjectForKey:@"Struts 2.x权威指南"];
29 [dict print];
30 }
31 }