关于 iOS 集合官方文档的一份小笔记

添加到 iOS 集合内的对象必须是对象。
做为集合,须要知足三个基本的特性:获取元素查找元素遍历元素
若是集合是可变的还须要另外支持 添加元素删除元素html

Array

添加到 Array 内的元素都是有序的,同一对象可屡次被添加到集合。和其它集合相比,Array 遍历内部元素十分方便。数组

Array 内元素必须是对象 (NSPointArray 除外)。bash

Array 的分类

  • NSArray 初始化后元素就不可再增删。app

  • NSMuatbleArray 初始化后能够随时添加或删除元素对象。ide

  • NSPointArrayNSMuatbleArray 类似,区别是能够指定对元素的强/弱引用。也就是说 NSPointArray 内部元素为对象 或 nil性能

关于数组的一些知识点:

  1. indexOfObjectindexOfObjectIdenticalTo 的区别?

两个方法都是来判断某一对象是不是 Array 集合内元素,若是是则返回该对象在集合内的索引。两个方法的区别就在于两个 API 断定的依据:indexOfObject 会使用 isEqualTo 方法将 Object 与集合元素进行比较。而 indexOfObjectIdenticalTo 则会比较 Object 与集合元素的指针是否相同。ui

  1. 关于数组排序,单一条件的值比较排序使用 SortedArrayUsingComparatorSortedArrayUsingSelector 很容易,若是给你两个甚至多个排序条件呢?好比对学生分数排序,排序条件为,优先按总分降序排列,总分相同再比较数学成绩降序排列,数学成绩也相同比较语文成绩降序排列··· ··· 前面的两个排序方法固然也能知足咱们的需求,可是如今要讨论的是另外一种更优雅的实现:使用 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

Dictionary 内部元素以 key:value 键值对的形式存在,添加到 Dictionary 内的键值对是无序的,而且具备同一 key 值的键值对对象重复添加会相互覆盖。当某个键值对添加到 Dictionary 时,Dictionary 会对 key 进行深拷贝,而对 value 进行浅拷贝,已经添加到集合内部的键值对,key 值将不可更改。而 value 值为强引用,当 value 为可变对象时,修改 value 对象,字典内的 value 也会被修改。spa

key 为任何遵循 NSCopying 协议并实现了 hashisEqual 方法的对象。
value 为任何对象(包括集合)翻译

key 须要很好地实现哈希方法,不然字典的设值、查找、获取、增长等操做耗时将线性增长。通常咱们都用 NSString 做为 key 值,是由于 NSString 很好地实现了哈希方法。这些操做的耗时为常量。

字典能够根据 value 值对 key 进行排序,排序后获得的是一个 key 数组。

Dictionary 的分类

  • NSDictionary 初始化后就不可再增删键值对。
  • NSMutableDictionary 初始化后能够随时添加或删除键值对。
  • NSMapTable 相似 NSMutableDictionary 能够指定对 value 的强/弱引用。也就是说 NSMapTable 内部元素的 value 值能够为 nil

关于字典的一些知识点:

咱们在使用 Dictionnary 时,通常将 String 做为 key 值 ,从而能够知足绝大部分需求。但有时也会遇到使用自定义对象做为 key 的状况。那么做为 key 的对象都须要知足哪些条件呢?

  1. key 必须遵循 NSCopying 协议,由于当元素渐入字典后,会对 key 进行深拷贝。
  2. key 必须实现 hashisEqual 方法。(便于快速获取元素并保证 key 的惟一性)。

并不建议使用特别大的对象做为 key,可能会致使性能问题。

Set

添加到 Set 内的元素都是无序的,同一对象只能被添加一次。和其它集合相比,Set 查找内部元素十分快速。

set 集合元素要很好地实现 hash 方法(时间复杂度为O(1)),不然时间复杂度为 O(k)

Set 的分类

  • NSSet 初始化后就不可再增删元素。
  • NSMuatbleSet 初始化后可随时增删元素。
  • NSCountedSet 每一个元素都带有一个计数,添加元素,计数为一。重复添加某个元素则计数加一;移除元素计数减一,计数为零则移除
  • NSHashTableNSMutableSet 相似,区别是可指定对元素的强/弱引用,内部元素能够为 nil

Index set

IndexSet 保存的 Array 子集,存储元素为 Arrayindex 索引,存储形式为索引范围。 eg: (0,3,4)->(NSRange(0,1),NSRange(3,2))

Index set 的分类

  • NSIndexSet 初始化后就不可再增删元素。
  • NSMutableIndexSet 初始化后可随时增删元素。

使用场景通常为记录数组的某些元素,好比列表多选行,可使用 NSIndexSet 来记录选择了哪行,而不是另外建立一个可变数组

Index path

保存嵌套数组的某个元素 path
如(0,2,0)

  • **NSIndexPath **

使用场景通常是 TableViewdataSource 代理方法。

严格意义上说,indexPath 并非集合。其只是记录嵌套数组内某子元素的路径位置。此处听从官方文档将 indexPath 和集合一块儿讨论。

深拷贝与浅拷贝

如下为官方定义,考虑到翻译后理解可能会出现误差,笔者并未进行翻译,墙裂建议读者本身阅读加深理解。

Shallow Copies

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.

Deep Copies

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 NSCodingprotocol. An example of this technique is shown in Listing 3.

Listing 3 A true deep copy

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];  

复制代码

参考

官方文档连接

相关文章
相关标签/搜索