OC Collections

简介

Collection是Foundation framework提供的用于存储和管理一组对象的类的集合。我们比较常用的有NSArray,NSDictionary和NSSet,这三者有共同点,也有不同点。

相同点

  • 可以遍历存储于其中的对象
  • 判断一个对象是不是存在于Collection中
  • 获取Collection中的一个对象
  • 可变性

大部分Collection中都只能存储对象(如果是int等非object类型,可以用NSNumber转化以后存入),且都有mutable和immutable两种形式,比如Array就分为NSArray和NSMutableArray,NSMutableArray是继承自NSArray的。如果一个Collection是mutable的,我们可以认为它比immutable的Collection多了以下两种能力:

  • 给Collection添加一个object
  • 从Collection中删除一个object

不可变的Collection最大的好处是线程安全,API绝对不能向外暴露可变的Collection。

不同点

虽然他们有很多共同点,但是也有很多不同点,了解这些不同点,有助于我们根据不同的情况选用适合的Collection,从而达到提高效率的目的,下面我们根据官方文档简单介绍一下他们的特点(Collections Programming Topics):

  • Arrays(如NSArray和NSMutableArray): 有序的,可以通过索引获取到索引相对的内容

1、用一个已有的array构造一个新的array,可以用下面这个方法创建:
-(instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
如果flag传NO,表示array中的object只是retain一份,并没有被copy;如果flag传YES,表示array中的object都被copy了新的一份。更多关于copy的内容见下面章节copying collections。

2、获取一个object的索引(可以用于判断object是否存在于Array中),可以采用以下两个方法:
-(NSUInteger)indexOfObject:(ObjectType)anObject;
-(NSUInteger)indexOfObjectIdenticalTo:(ObjectType)anObject;
第一个方法只要值一致就可以了,第二个方法比较指针一致。

3、排序

  • sorting with sort descriptions
  • sorting with blocks
  • sorting with functions and selectors
  • Dictionaries(如NSDictionary和NSMutableDictionary):无序的,通过key-value的形式获取存储的内容,提供快速的insertion和deletion操作。

1、与Array相似,用构造函数 initWithDictionary:copyItems:新建一个Dictionary,在copyItems传NO的情况下,Dictionary中value的object没有做深拷贝。
2、key可以是任何一个实现了NSCopying协议,并且实现了 hash 和 isEqual:方法的object。由于Dictionary内部用一个hash table来管理存储在其内部的object,所以hash方法的效率直接影响查找value的效率。一般用NSString对象来作为key可以满足大部分需求。
如果key没有实现NSCopying协议,直接跑出runtime error,没有实现hash和isEqual方法的话,无法查找存储在hash table中key对应的value,hash方法的实现应该尽量保证唯一性。NSObject默认的hash方法如下,默认的hash方法仅仅返回对象指针的地址,同样的isEqual也仅仅比较两个对象的指针地址是否相等。如果NSObject对于这两个方法的实现可以满足需求,就不需要重写。


 - (NSUInteger)hash {
     return (NSUInteger)self; 
 }

3、Sort
Dictionary提供了根据key的排序输出value的方法

  • Sets(如NSSet,NSMutableSet和NSCountedSet):无序的,提供快速的insertion和deletion操作,还提供快速查找一个object是否存在于set中;其中,NSSet和NSMutableSet中的内容不可重复,NSCountedSet中的object可以重复添加,但是同一个object添加多次只有一个object实例,NSCountedSet对于其中的object维护一个计数器,当添加的次数等于去除的次数,改object的实例会从Set中被remove掉。简单地说,set管理的是一些不重复的无序的object的集合(NSCountedSet除外,可以重复)。

1、initWithSet:copyItems:新建一个Set,在copyItems传NO的情况下,Set中的Object没有做深拷贝
2、set中的每个Object必须实现NSObject协议中的hash和IsEqual方法。
3、set没有排序方法,可以通过allObjects方法把set转化为array。
4、set的优势在判断object在不在一个set中,mutable set提供了一系列。


unionSet:
 adds all the objects from another set which are not already present.

intersectSet:
 removes all the objects which are not in another set.

minusSet:
 removes all the objects which are in another set.
图1 NSArray,NSDictionary和NSSet

Copying Collections

  • 浅拷贝和深拷贝(如图2所示)


    图2 浅拷贝和深拷贝

浅拷贝仅给object发送一个retain消息,拷贝指针;深拷贝给object发送一个copyWithZone:消息,因此必须让object实现NSCopying协议。如果没有实现copyWithZone,将会抛出一个runtime error,如图3所示

图3

实现NSCopying协议仅仅实现了one-deep-level copy,如果你要实现true deep copy,例如你想要archive和unarchive一个Collection,必须实现NSCoding协议,如果不实现NSCoding协议,直接archive,报如图4的错,遵循NSCoding协议的Object可以被序列化和反序列化


图4.png

遍历(Enumeration)

  • for循环
    优点:可以获得Index,可以反向遍历;
    缺点:需要创建中间对象

//Array
for (NSUInteger i = 0; i < Array.count; i++) {
    id object = Array[i]
}
//Dictionary
NSArray *keys = [Dictionary allKeys];
for (NSUInteger i = 0; i < keys.count; i++) {
    id key = keys[i];
    id object = [Dictionary objectForKey:key];
}
//Set
NSArray *tranArray = [Set allObjects];
Then same with array
  • Fast Enumeration
    优点:语法简洁,无中间变量,可以反向遍历[array reverseObjectEnumerator]
    缺点:无法获得index

//Array
for(id object in self.testArray){
    
}

//Dictionay
for(id key in self.testDic){
    id object = [self.testDic objectForKey:key];
}

//Set
for(id object in self.testSet) {
    
} 

<NSFastEnumeration>协议只提供一个方法,如果需要一个类的对象实现快速遍历,就通过实现该协议来实现。


- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len;
  • Block Enumeration(推荐)
    优点:可以获取index,不用生成中间变量,方便实现反向遍历,对于比较耗时的任务实现并发遍历比较方便,提供停止遍历的变量。
    缺点:基本没有。

//Array
[Array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    
}];

//Dictionary
[Dictionary enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
}];

//Set
[Set enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
    
}];
//另一个block遍历方法,以Array为例,Dictionary和Set分别也实现了对应的方法。
//NSEnumerationOptions是一个枚举类型,   
//NSEnumerationConcurrent实现每次遍历的块可以并发执行,对于耗时且顺序不重要的遍历可以使用并发遍历;NSEnumerationReverse实现反向遍历。
[Array enumerateObjectsWithOptions:(NSEnumerationOptions) usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    
}];

typedef NS_OPTIONS(NSUInteger, NSEnumerationOptions) {
    NSEnumerationConcurrent = (1UL << 0),
    NSEnumerationReverse = (1UL << 1),
};
  • NSEnumerator(不建议)
    NSEnumerator是一个抽象类,仅仅定义了两个方法供子类来实现,array,set,dictionary提供了special NSEnumerator objects来遍历自身的objects。这两个方法是:

- (nullable ObjectType)nextObject;
@property (readonly, copy) NSArray<ObjectType> *allObjects;

nextObject返回Collection中的下一个object,如果没有下一个object,返回nil。

Test Source Code

https://github.com/syjazg/share.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,218评论 11 349
  • Java 语言支持的类型分为两类:基本类型和引用类型。整型(byte 1, short 2, int 4, lon...
    xiaogmail阅读 1,346评论 0 10
  • 小花沾雨露 小草随风摇 青青似吾心 丝丝如吾情
    3369b70d4c9f阅读 181评论 0 0
  • 什么是情感引导 情感引导就是向孩子传授情感规则,让他们知道如何辨认情感并且以恰当的方式来表达。 父母管教孩子的常见...
    日更飘阅读 232评论 0 0
  • 山腰上的战斗已经到了白热化,人类军队开始同犬蜥人展开混战,这时,正规军团与部落民军的差距就出来了,战阵对抗,擅...
    龙骑魔将阅读 363评论 0 1