做app的时候,总免不了要多次遍历数组或者字典。
究竟哪种遍历方式比较快呢?我做了如下测试:
首先定义测试用宏:

1
2
3
4
5
6
7
8
9
#define
MULogTimeintervalBegin(INFO) NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];\
NSTimeInterval

duration = 0;\
NSLog(@"MULogTimeintervalBegin:%@",
INFO)
 
#define
MULogTimeintervalPauseAndLog(INFO) duration = [NSDate timeIntervalSinceReferenceDate] - start;\
start
+= duration;\
NSLog(@"%@:%f",
INFO, duration);\
duration
= 0
#define
TESTSCALE 100000

接着编写测试代码:
NSarray:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-
(
void)testArray
{
    NSMutableArray*
testArray = [
NSMutableArray

arrayWithCapacity:TESTSCALE];
    for

(
NSInteger

i = 1; i <= TESTSCALE; ++i) {
        [testArray
addObject:[
NSString

stringWithFormat:@
"%ld",
i]];
    }
    NSLog(@"init:%ld",
[testArray count]);
     
    __block
NSMutableString*
sum = [
NSMutableString

stringWithCapacity:TESTSCALE];
     
    MULogTimeintervalBegin(@"ArrayTest");
    NSUInteger

count = [testArray count];
    for

(
NSInteger

i = 0; i < count; ++i) {
        [sum
appendString:[testArray objectAtIndex:i]];
    }
    [sum
setString:@
""];
    MULogTimeintervalPauseAndLog(@"for
statement"
);
     
    for(NSString*
item in testArray) {
        [sum
appendString:item];
    }
    [sum
setString:@
""];
    MULogTimeintervalPauseAndLog(@"for-in");
     
    [testArray
enumerateObjectsUsingBlock:^(
id

obj,
NSUInteger

idx,
BOOL

*stop) {
        [sum
appendString:obj];
    }];
    [sum
setString:@
""];
    MULogTimeintervalPauseAndLog(@"enumerateBlock");
}

NSDictionary:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-
(
void)testDictionary
{
    NSMutableDictionary*
testDic = [
NSMutableDictionary

dictionaryWithCapacity:TESTSCALE];
    for

(
NSInteger

i = 1; i <= TESTSCALE; ++i) {
        [testDic
setObject:@
"test"

forKey:[
NSString

stringWithFormat:@
"%ld",
i]];
    }
    NSLog(@"init:%ld",
[testDic count]);
     
    __block
NSMutableString*
sum = [
NSMutableString

stringWithCapacity:TESTSCALE];
     
    MULogTimeintervalBegin(@"DictionaryTest");
    for

(
NSString*
object in [testDic allValues]) {
        [sum
appendString:object];
    }
    [sum
setString:@
""];
    MULogTimeintervalPauseAndLog(@"for
statement allValues"
);
     
    for

(
id

akey in [testDic allKeys]) {
        [sum
appendString:[testDic objectForKey:akey]];
    }
    [sum
setString:@
""];
    MULogTimeintervalPauseAndLog(@"for
statement allKeys"
);
     
    [testDic
enumerateKeysAndObjectsUsingBlock:^(
id

key,
id

obj,
BOOL

*stop) {
        [sum
appendString:obj];
    }
];
    MULogTimeintervalPauseAndLog(@"enumeration");
}

下面是测试结果:
Test Case '-[LoopTestTests testArray]' started.
2012-08-02 17:14:22.061 otest[388:303] init:100000
2012-08-02 17:14:22.062 otest[388:303] MULogTimeintervalBegin:ArrayTest
2012-08-02 17:14:22.075 otest[388:303]for statement:0.013108
2012-08-02 17:14:22.083 otest[388:303]for-in:0.008186
2012-08-02 17:14:22.095 otest[388:303] enumerateBlock:0.012290
Test Case '-[LoopTestTests testArray]' passed (0.165 seconds).
Test Case '-[LoopTestTests testDictionary]' started.
2012-08-02 17:14:22.273 otest[388:303] init:100000
2012-08-02 17:14:22.274 otest[388:303] MULogTimeintervalBegin:DictionaryTest
2012-08-02 17:14:22.284 otest[388:303] for statement allValues:0.010566
2012-08-02 17:14:22.307 otest[388:303] for statement allKeys:0.022377
2012-08-02 17:14:22.330 otest[388:303] enumeration:0.023914
Test Case '-[LoopTestTests testDictionary]' passed (0.217 seconds).

可以看出对于数组来说,for-in方式遍历速度是最快的,普通风格的for和block方式速度差不多。对于字典来说,allValues方式遍历最快,allKeys和block差不多。
那么,为什么会这样呢?
NSArray:

1
2
3
for

(
NSInteger

i = 0; i < count; ++i) {
        [sum
appendString:[testArray objectAtIndex:i]];
}

这里由于存在:[objectAtIndex:i]这样的取操作,所以速度会有所下降。

1
2
3
for(NSString*
item in testArray) {
        [sum
appendString:item];
}

尽管也有取操作,但是绕开了oc的message机制,速度会快一点。也有可能是编译器为了for-in作了优化。
block为什么会慢一些这个有待研究。
NSDictionary:

1
2
3
for

(
id

akey in [testDic allKeys]) {
        [sum
appendString:[testDic objectForKey:akey]];
}

这个就很明显了,第二种方法多了一次objectForKey的操作。block的话有待研究。


google了一下,stackoverflow上面有类似的讨论:点击打开链接
大意是:for-in语法会对容器里面的元素的内存地址建立一个缓冲,遍历的时候从缓冲直接取得元素的地址而不是通过调用方法来获取,所以效率比较高。另外,这也是不能在循环体中修改容器元素的原因之一。

oc/object-c/ios哪种遍历NSArray/NSDictionary方式快?测试报告的更多相关文章

  1. iOS五种本地缓存数据方式

    iOS五种本地缓存数据方式   iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...

  2. 遍历NSArray, NSDictionary, NSSet的方法总结

    1,for循环读取 NSArray: NSArray *array = /*…*/ ; i<array.count; i++) { id object = array[i]; // do sth ...

  3. HashMap两种遍历数据的方式

    HashMap的遍历有两种方式,一种是entrySet的方式,另外一种是keySet的方式. 第一种利用entrySet的方式: Map map = new HashMap(); Iterator i ...

  4. iOS - 数组与字典(NSArray & NSDictionary)

    1. 数组的常用处理方式 //--------------------不可变数组 //1.数组的创建 NSString *s1 = @"zhangsan"; NSString *s ...

  5. [集合]Map的 entrySet() 详解以及用法(四种遍历map的方式)

    Entry 由于Map中存放的元素均为键值对,故每一个键值对必然存在一个映射关系. Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value (我们总说键值对键值对, 每一个键值对也 ...

  6. IOS四种保存数据的方式

    在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyed ...

  7. IOS 四种保存数据的方式

    在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题.将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好.下面介绍一下数据保存的方式: 1.NSKeyed ...

  8. Java中五种遍历HashMap的方式

    import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class Java8Templat ...

  9. 另一种遍历Map的方式: Map.Entry 和 Map.entrySet()

    源网址: http://blog.csdn.net/mageshuai/article/details/3523116 今天看Think in java 的GUI这一章的时候,里面的TextArea这 ...

随机推荐

  1. 14个最常见的Kafka面试题及答案【转】

    原创 IT168企业级 2017-08-21 17:40 本文为您盘点了14个最常见的Kafka面试题,同时也是对Apache Kafka初学者必备知识点的一个整理与介绍. 1.请说明什么是Apach ...

  2. angular项目文件概览

    在Mac上打开终端,输入ng new b-app  如下: 然后在webstorm中打开 src文件夹 你的应用代码位于src文件夹中. 所有的Angular组件.模板.样式.图片以及你的应用所需的任 ...

  3. jmeter------reponse报错”Unknown column 'XXXXX' in 'where clause'“

    一.问题描述 jmeter添加了与数据库mysql的连接,编写完JDBC Request之后,运行提示报错”Unknown column 'be7f5b6e750bb6becf855386338644 ...

  4. springcloud 出现unavailable-replicas

    springcloud 出现unavailable-replicas 原因: 1. 部分服务不可用 2. 直接使用了ip地址作为hostname application.properties # 不能 ...

  5. hadoop环境安装及错误总结

    历时N天的hadoop环境,终于配好了 主要参考 Hadoop集群安装配置教程_Hadoop2.6.0_Ubuntu/CentOS 1.开机默认进入字符界面或者是图形界面:http://blog.cs ...

  6. layer弹出层的关闭问题

    就是在执行添加或修改的时候,需要将数据提交到后台进行处理,这时候添加成功之后最理想的状态是关闭弹出层并且刷新列表的数据信息,之前一直想实现这样,可一直没有成功,今天决定好好弄一弄,在仔细看过layer ...

  7. 不通过注册表使用ActiveX对象

    为了弄清楚COM库的运行原理,特意做了这个实验: #include "stdafx.h" #include "objbase.h" #include " ...

  8. Docker入门到实战

    1.系统要求 Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10. CentOS 7满足最低内核的要求,但由于内核版本比较低,部分功能(如 overlay2 存 ...

  9. Dijkstra【P2446】 [SDOI2010]大陆争霸

    Background 在一个遥远的世界里有两个国家:位于大陆西端的杰森国和位于大陆东端的克里斯国.两个国家的人民分别信仰两个对立的神:杰森国信仰象征黑暗和毁灭的神曾·布拉泽,而克里斯国信仰象征光明和永 ...

  10. Unity 2D游戏开发教程之2D游戏的运行效果

    Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑问 ...