添加到 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]];
複製代碼