添加到 iOS 集合内的对象必须是对象。
做为集合,须要知足三个基本的特性:获取元素、查找元素、遍历元素;
若是集合是可变的还须要另外支持 添加元素 和 删除元素。html
添加到 Array
内的元素都是有序的,同一对象可屡次被添加到集合。和其它集合相比,Array
遍历内部元素十分方便。数组
Array
内元素必须是对象 (NSPointArray
除外)。bash
NSArray 初始化后元素就不可再增删。app
NSMuatbleArray 初始化后能够随时添加或删除元素对象。ide
NSPointArray 与 NSMuatbleArray
类似,区别是能够指定对元素的强/弱引用。也就是说 NSPointArray
内部元素为对象 或 nil
。性能
indexOfObject
与 indexOfObjectIdenticalTo
的区别?两个方法都是来判断某一对象是不是 Array
集合内元素,若是是则返回该对象在集合内的索引。两个方法的区别就在于两个 API 断定的依据:indexOfObject
会使用 isEqualTo
方法将 Object
与集合元素进行比较。而 indexOfObjectIdenticalTo
则会比较 Object
与集合元素的指针是否相同。ui
SortedArrayUsingComparator
或 SortedArrayUsingSelector
很容易,若是给你两个甚至多个排序条件呢?好比对学生分数排序,排序条件为,优先按总分降序排列,总分相同再比较数学成绩降序排列,数学成绩也相同比较语文成绩降序排列··· ··· 前面的两个排序方法固然也能知足咱们的需求,可是如今要讨论的是另外一种更优雅的实现:使用 NSSortDescriptor
。Student *p1 = [[Student alloc] initWithName:@"zhonger" id:@"1" score:552 math:130 chinese:90 english:120];
Student *p2 = [[Student alloc] initWithName:@"zhonger" id:@"1" score:552 math:130 chinese:90 english:120];
Student *p3 = [[Student alloc] initWithName:@"zhonger" id:@"1" score:552 math:130 chinese:90 english:120];
Student *p4 = [[Student alloc] initWithName:@"zhonger" id:@"1" score:552 math:130 chinese:90 english:120];
Student *p5 = [[Student alloc] initWithName:@"zhonger" id:@"1" score:552 math:130 chinese:90 english:120];
NSArray *students = @[p1, p2, p3, p4, p5];
NSSortDescriptor *des1 = [[NSSortDescriptor alloc]initWithKey:@"score" ascending:NO];
NSSortDescriptor *des2 = [[NSSortDescriptor alloc] initWithKey:@"math" ascending:NO];
NSSortDescriptor *des3 = [[NSSortDescriptor alloc] initWithKey:@"chinese" ascending:NO];
NSArray *newArray1 = [students sortedArrayUsingDescriptors:@[des1,des2,des3]];
NSLog(@"%@",newArray1);
复制代码
是否是比以前的排序方法可读性提高了不少,并且代码后期也更好维护。this
Dictionary
内部元素以 key:value
键值对的形式存在,添加到 Dictionary
内的键值对是无序的,而且具备同一 key
值的键值对对象重复添加会相互覆盖。当某个键值对添加到 Dictionary
时,Dictionary
会对 key
进行深拷贝,而对 value
进行浅拷贝,已经添加到集合内部的键值对,key 值将不可更改。而 value 值为强引用,当 value
为可变对象时,修改 value
对象,字典内的 value
也会被修改。spa
key
为任何遵循 NSCopying
协议并实现了 hash
和 isEqual
方法的对象。
value
为任何对象(包括集合)翻译
key
须要很好地实现哈希方法,不然字典的设值、查找、获取、增长等操做耗时将线性增长。通常咱们都用 NSString
做为 key
值,是由于 NSString
很好地实现了哈希方法。这些操做的耗时为常量。
字典能够根据 value
值对 key
进行排序,排序后获得的是一个 key
数组。
NSMutableDictionary
能够指定对 value
的强/弱引用。也就是说 NSMapTable
内部元素的 value
值能够为 nil
。咱们在使用 Dictionnary
时,通常将 String
做为 key
值 ,从而能够知足绝大部分需求。但有时也会遇到使用自定义对象做为 key 的状况。那么做为 key
的对象都须要知足哪些条件呢?
key
必须遵循 NSCopying
协议,由于当元素渐入字典后,会对 key
进行深拷贝。key
必须实现 hash
与 isEqual
方法。(便于快速获取元素并保证 key
的惟一性)。并不建议使用特别大的对象做为
key
,可能会致使性能问题。
添加到 Set 内的元素都是无序的,同一对象只能被添加一次。和其它集合相比,Set 查找内部元素十分快速。
set
集合元素要很好地实现hash
方法(时间复杂度为O(1)),不然时间复杂度为 O(k)
nil
。IndexSet
保存的 Array
子集,存储元素为 Array
的 index
索引,存储形式为索引范围。 eg: (0,3,4)->(NSRange(0,1),NSRange(3,2))
使用场景通常为记录数组的某些元素,好比列表多选行,可使用 NSIndexSet
来记录选择了哪行,而不是另外建立一个可变数组
保存嵌套数组的某个元素 path
如(0,2,0)
使用场景通常是 TableView
的 dataSource
代理方法。
严格意义上说,
indexPath
并非集合。其只是记录嵌套数组内某子元素的路径位置。此处听从官方文档将indexPath
和集合一块儿讨论。
如下为官方定义,考虑到翻译后理解可能会出现误差,笔者并未进行翻译,墙裂建议读者本身阅读加深理解。
There are a number of ways to make a shallow copy of a collection. When you create a shallow copy, the objects in the original collection are sent a retain
message and the pointers are copied to the new collection. Listing 1 shows some of the ways to create a new collection using a shallow copy.
Listing 1 Making a shallow copy
NSArray *shallowCopyArray = [someArray copyWithZone:nil];
NSDictionary *shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:NO];
复制代码
These techniques are not restricted to the collections shown. For example, you can copy a set with the copyWithZone:
method—or the mutableCopyWithZone:
method—or an array with initWithArray:copyItems:
method.
There are two ways to make deep copies of a collection. You can use the collection’s equivalent of initWithArray:copyItems:
with YES
as the second parameter. If you create a deep copy of a collection in this way, each object in the collection is sent a copyWithZone:
message. If the objects in the collection have adopted the NSCopying
protocol, the objects are deeply copied to the new collection, which is then the sole owner of the copied objects. If the objects do not adopt the NSCopying
protocol, attempting to copy them in such a way results in a runtime error. However, copyWithZone:
produces a shallow copy. This kind of copy is only capable of producing a one-level-deep copy. If you only need a one-level-deep copy, you can explicitly call for one as in Listing 2.
Listing 2 Making a deep copy
This technique applies to the other collections as well. Use the collection’s equivalent of initWithArray:copyItems:
with YES
as the second parameter.
If you need a true deep copy, such as when you have an array of arrays, you can archive and then unarchive the collection, provided the contents all conform to the NSCoding
protocol. An example of this technique is shown in Listing 3.
Listing 3 A true deep copy
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];
复制代码