教你用正確的姿勢(shì)遍歷OC中的collection

引言

無論那種語(yǔ)言,我們都會(huì)大量的去操作collection(集合),對(duì)collection不停的做增刪該查,OC也不例外。而當(dāng)我們對(duì)collection做操作的時(shí)候應(yīng)該時(shí)刻關(guān)注操作復(fù)雜度,包括時(shí)間復(fù)雜度和空間復(fù)雜度,使自己的代碼用盡可能低的內(nèi)存消耗和盡可能少的時(shí)間來完成需求。本文旨在以“黑盒”的方式來比較OC中用不同的方法遍歷NSMutableArray和NSMutableDictionary中的值所用的時(shí)間。

環(huán)境

  • MACBook Pro 2.7 GHz Intel Core i5
  • MAC OS X 10.11.6 (15G1004)
  • XCode Version 8.2 (8C38)

步驟

1,創(chuàng)建ZMTest工程,在ViewController中定義如下屬性

@property (nonatomic, strong) NSMutableArray *testArray;
@property (nonatomic, strong) NSMutableDictionary *testDictionary;

2,初始化

self.testArray = [NSMutableArray new];
self.testDictionary = [NSMutableDictionary new];

for (int i = 0; i <= 10000000; i ++) {
    NSString *value = [NSString stringWithFormat:@"%d",i];
    [self.testArray addObject:value];
    [self.testDictionary setValue:value forKey:value];
}

3,引入獲取代碼運(yùn)行時(shí)間的宏(這是公司一個(gè)大神寫的,地址

/** 快速查詢一段代碼的執(zhí)行時(shí)間 */
/** 用法
TICK
do your work here
TOCK
*/
#define TICK NSDate *startTime = [NSDate date];
#define TOCK NSLog(@"Time:%f\n", -[startTime timeIntervalSinceNow]);

4,實(shí)現(xiàn)如下方法

- (void)testArraty1{
TICK

for (int i = 0; i < self.testArray.count; i ++) {
    if ([self.testArray[i] isEqualToString:@"10000000"]) {
        NSLog(@"testArraty1");
    }
}
TOCK
}

- (void)testArraty2{
TICK
NSInteger *index = 0;
for (NSString *value in self.testArray) {
    index  = index + 1;
    if ([value isEqualToString:@"10000000"]) {
        NSLog(@"testArraty2");
    }
}
TOCK
}

- (void)testArraty3{
  TICK
  [self.testArray enumerateObjectsUsingBlock:^(NSString * value, NSUInteger i, BOOL * _Nonnull stop) {
      if ([value isEqualToString:@"10000000"]) {
          NSLog(@"testArraty3");
      }
  }];
  TOCK
  }

- (void)testDictionary1{
TICK
[self.testDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL * _Nonnull stop) {
    if ([key isEqualToString:@"10000000"]) {
        NSLog(@"testDictionary1");
    }
}];
TOCK
}

- (void)testDictionary2{
TICK

NSArray *allKey = [self.testDictionary allKeys];
for (NSString * key in allKey) {
    NSString *value = self.testDictionary[key];
    if ([key isEqualToString:@"10000000"]) {
        NSLog(@"testDictionary2");
    }
}

TOCK
}

然后再viewDidLoad方法中調(diào)用這幾個(gè)方法

5,運(yùn)行,結(jié)果如下

Paste_Image.png

以下是整理的表格

方法 耗時(shí) 說明
testArraty1 1.530919 Execute code for each value in a sequence of values(不會(huì)翻譯??,就是最簡(jiǎn)單的for循環(huán))
testArraty2 0.131923 NSFastEnumeration協(xié)議方法
testArraty3 0.489827 基于塊的遍歷
testDictionary1 0.674507 基于塊的遍歷
testDictionary2 2.830808 通過allKey是方法獲取所有的key,然后通過key獲取value

6,結(jié)論

(1)在遍歷NSArray的時(shí)候最好使用NSFastEnumeration協(xié)議的這種方式(for...in...),效率明顯高于通過定義索引然后檢索的方式,當(dāng)然為了操作簡(jiǎn)單,也可以使用基于塊的方式來遍歷,基于block的方式遍歷的好處也顯而易見,直接可以獲取到下標(biāo)、值和跳出循環(huán)的BOOL值,當(dāng)然該方式的的耗時(shí)也高于NSFastEnumeration協(xié)議的方式,不過,我覺得可以接受。

(2)在遍歷NSDictionary的時(shí)候,請(qǐng)務(wù)必使用基于block的形式,不僅大量的降低時(shí)耗,而且能獲取到key、value和跳出循環(huán)的BOOL值??芍^方便快捷。

最后

接觸的新東西的越多。越覺得自己欠缺,最近在看《編寫高質(zhì)量IOS與OS X代碼的52個(gè)有效方法》一書,真心推薦。而本文也算是書中一個(gè)章節(jié)的讀后感。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,604評(píng)論 30 472
  • Object-c的類可以多重繼承么?可以實(shí)現(xiàn)多個(gè)接口么?Category是什么?重寫一個(gè)類的方式用繼承好還是分類好...
    small_Sun閱讀 779評(píng)論 0 0
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,184評(píng)論 4 61
  • 一、這個(gè)實(shí)戰(zhàn)項(xiàng)目是計(jì)劃跨平臺(tái)開發(fā)的,既要開發(fā)Android版本,也要開發(fā)IOS版本,所以: 1、需要Mac電腦,實(shí)...
    psx900910閱讀 288評(píng)論 0 0
  • 《清平樂》上闋 宋·辛棄疾 茅檐低小,溪上青青草。 醉里吳音相媚好, 白發(fā)誰(shuí)家翁媼?
    喜亭_bf8f閱讀 244評(píng)論 0 7

友情鏈接更多精彩內(nèi)容